最近做了个播放页面,标题和一个iframe;需要对这个iframe可以进行网页涂鸦。
网页涂鸦肯定是canvas了。网上找了个差不多的,实验下来问题很多,干脆自己一步步修改,学习。

效果:

本项目没有引入其他的任何工具库,复制代码可以直接运行,下面贴出代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>小小英语-阅读</title>
<meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="format-detection" content="telephone=no">
<meta name="description" content="数千册优质分级阅读绘本">
<style>
*{
padding:0;margin:0;
}
li{
list-style-type:none;
}
html,body{
height:100%;
}
.content-page{
min-width:1500px;
min-height: 100%;
background:#f6f6f6;
}
#page{
position:relative;
width:1200px;
margin:0 auto;
border-top:1px solid rgba(0,0,0,0)
}
h3{
position: relative;
margin:40px 0;
color:#ff8e5d;
font-size:30px;
text-align:center;
}
.back{
position:absolute;
left:0;
top:50%;
transform:translate(0,-50%);
font-family:PingFang-SC-Regular;
font-size:20px;
padding-left:20px;
background:url('../assets/images/icon_back-red.png') no-repeat;
background-size:20px 20px;
}
#content-iframe{
width:100%;
background: #ccc;
min-height: 800px;
border:none; }
#canvas{
position:absolute;
left:0;
top:0;
z-index:100;
cursor:default;
top:120px;
left:50%;
transform:translate(-50%,0);
display: none;/*canvas刚进来是隐藏的,需要选颜色激活*/
}
.right-bar{
width:100px;
position: absolute;
right:-120px;
top:120px;
color:#000;
z-index:1;
}
.word{
font-size:24px;
font-family:FredokaOne-Regular;
color:rgba(255,142,93,1);
text-align:center;
}
.right-bar>span{
display: block;
width:90px;
height:40px;
color:#fff;
font-size:16px;
padding:0;
line-height: 40px;
border:none;
background: #FF8E5D;
margin:18px auto;
text-align: center;
cursor: pointer;
}
.btn-active{background:#ED723D !important}
#color{
padding-left:8px;
margin-top:10px;
}
#color>i{
position:relative;
display:inline-block;
width:34px;
height:34px;
border-radius: 50%;
margin-right:8px;
margin-bottom:5px;
border:none;
cursor: pointer;
z-index:50;
}
.color-active{
position:absolute;
top:50%;
left:50%;
transform:translate(-50%,-50%); display: block;
border: 1px solid #FF8E5D;
border-radius: 50%;
width:40px;
height:40px;
z-index:40;
display: none;
}
.i1{
background:#DF4BFF;
}
.i2{
background:#9CCB68;
}
.i3{
background:#3DC1FF;
}
.i4{
background:#FFD338;
}
.i5{
background:#FF6262;
}
.i6{
background: #000000;
}
</style>
</head>
<body>
<div class="content-page">
<div id="page">
<h3>
标题
<p class="back" @click="goBack()">
返回上一级
</p>
</h3>
<iframe id="content-iframe" :src="iframeUrl"> </iframe>
<div class="right-bar">
<div class="word">color</div>
<div id="color">
<i class="i1"><span class="color-active"></span></i>
<i class="i2"><span class="color-active"></span></i>
<i class="i3"><span class="color-active"></span></i>
<i class="i4"><span class="color-active"></span></i>
<i class="i5"><span class="color-active"></span></i>
<i class="i6"><span class="color-active"></span></i>
</div> <span id="eraser">橡皮擦</span>
<span id="revocation">撤销</span>
<span id="clear">清除</span>
<span id="hide" class="btn-active">关闭</span> </div>
</div> <canvas id="canvas" width="740" height="420">您的<u>浏览器</u>不支持 canvas 标签</canvas> </div>
<script type="text/javascript">
var paint={
load:function(){
this.x=[];//记录鼠标移动是的X坐标
this.y=[];//记录鼠标移动是的Y坐标
this.clickDrag=[];
this.lock=false;//鼠标移动前,判断鼠标是否按下
this.isEraser=false;
this.storageColor="#f00";
this.eraserRadius=15;//擦除半径值
this.color=["#DF4BFF","#9CCB68","#3DC1FF","#FFD338","#FF6262","#000000"];//画笔颜色
this.$=function(id){return typeof id=="string"?document.getElementById(id):id;};
this.canvas=this.$("canvas");
this.canvas.width=this.$('content-iframe').offsetWidth;//设定canvas的宽度
this.canvas.height=this.$('content-iframe').offsetHeight;//设定canvas的高度
if (!this.canvas.getContext) {
alert("您的浏览器不支持 canvas 标签");
return;
}
this.cxt=this.canvas.getContext('2d');
this.cxt.lineJoin = "round";//context.lineJoin - 指定两条线段的连接方式
this.cxt.lineWidth = 5;//线条的宽度
this.iptClear=this.$("clear");
this.revocation=this.$("revocation");
this.hide = this.$('hide');
this.eraser = this.$('eraser'); this.colorSpan = this.$('color').getElementsByTagName('span');//颜色的外框的span集合
this.imgArr = [];//保存每个状态,撤销的时候用到
this.touch =("createTouch" in document);//判定是否为手持设备
this.StartEvent = this.touch ? "touchstart" : "mousedown";//支持触摸式使用相应的事件替代
this.MoveEvent = this.touch ? "touchmove" : "mousemove";
this.EndEvent = this.touch ? "touchend" : "mouseup";
this.bind();
},
bind:function(){
var t=this;
this.hide.onclick = function(){
t.canvas.style.display = 'none';
t.eraser.className = "";
t.hide.className = 'btn-active'
t.hideColorSpan();
}
/*清除画布*/
this.iptClear.onclick=function(){
t.cxt.clearRect(0, 0, t.canvas.width, t.canvas.height-1);
};
/*鼠标按下事件,记录鼠标位置,并绘制,解锁lock,打开mousemove事件*/
this.canvas['on'+t.StartEvent]=function(e){
// debugger;
t.imgArr.push(t.cxt.getImageData(0, 0,t.canvas.width,t.canvas.height));
var touch=t.touch ? e.touches[0] : e;
var box = t.canvas.getBoundingClientRect();
var _x = (touch.clientX - box.left) * t.canvas.width / box.width
var _y = (touch.clientY - box.top) * t.canvas.height / box.height
if(t.isEraser){
t.resetEraser(_x,_y,touch);
}else{
t.movePoint(_x,_y);//记录鼠标位置
t.drawPoint();//绘制路线
}
t.lock=true;
};
/*鼠标移动事件*/
this.canvas['on'+t.MoveEvent]=function(e){
// console.log(t.touch);
var touch=t.touch ? e.touches[0] : e;
//var touch = e;
if(t.lock){
var touch=t.touch ? e.touches[0] : e;
var box = t.canvas.getBoundingClientRect();
var _x = (touch.clientX - box.left) * t.canvas.width / box.width
var _y = (touch.clientY - box.top) * t.canvas.height / box.height
if(t.isEraser){
t.resetEraser(_x,_y,touch);
}
else{
t.movePoint(_x,_y,true);//记录鼠标位置
t.drawPoint();//绘制路线
}
}
};
this.canvas['on'+t.EndEvent]=function(e){
/*重置数据*/
t.lock=false;
t.x=[];
t.y=[];
t.clickDrag=[];
clearInterval(t.Timer);
t.Timer=null; };
this.revocation.onclick=function(){
if(t.imgArr.length>0){
t.cxt.putImageData(t.imgArr[t.imgArr.length-1], 0, 0);
t.imgArr.pop();
} };
this.changeColor();
/*橡皮擦*/
this.$("eraser").onclick=function(e){
if(t.hide.className ===''){
t.hideColorSpan();//这里是
t.isEraser=true;
t.eraser.className = 'btn-active';
} };
},
movePoint:function(x,y,dragging){
// debugger;
/*将鼠标坐标添加到各自对应的数组里*/
this.x.push(x);
this.y.push(y);
this.clickDrag.push(y);
},
drawPoint:function(x,y,radius){
for(var i=0; i < this.x.length; i++){
this.cxt.beginPath();//context.beginPath() , 准备绘制一条路径
if(this.clickDrag[i] && i){//当是拖动而且i!=0时,从上一个点开始画线。
this.cxt.moveTo(this.x[i-1], this.y[i-1]);//context.moveTo(x, y) , 新开一个路径,并指定路径的起点
}else{
this.cxt.moveTo(this.x[i]-1, this.y[i]);
}
this.cxt.lineTo(this.x[i], this.y[i]);//context.lineTo(x, y) , 将当前点与指定的点用一条笔直的路径连接起来
this.cxt.closePath();//context.closePath() , 如果当前路径是打开的则关闭它
this.cxt.stroke();//context.stroke() , 绘制当前路径
}
},
preventDefault:function(e){
/*阻止默认*/
var touch=this.touch ? e.touches[0] : e;
if(this.touch)touch.preventDefault();
else window.event.returnValue = false;
},
changeColor:function(){
/*为按钮添加事件*/
var t=this,iptNum=this.$("color").getElementsByTagName("i");
for(let i=0,l=iptNum.length;i<l;i++){//这里要么用let,要么用闭包
iptNum[i].index=i;
iptNum[i].onclick=function(){
t.hideColorSpan();//隐藏所有颜色的选中
t.colorSpan[i].style.display = 'block'//选中点击的颜色
t.canvas.style.display = 'block';
// debugger;
t.cxt.save();
t.cxt.strokeStyle = t.color[this.index];
t.storageColor=t.color[this.index];
t.$("hide").className = '';
t.$("eraser").className = '';//清除橡皮擦选中状态
t.cxt.strokeStyle = t.storageColor;
t.isEraser=false;
}
}
},
resetEraser:function(_x,_y,touch){
var t=this;
//this.cxt.lineWidth = 30;
/*source-over 默认,相交部分由后绘制图形的填充(颜色,渐变,纹理)覆盖,全部浏览器通过*/
t.cxt.globalCompositeOperation = "destination-out";
t.cxt.beginPath();
t.cxt.arc(_x, _y, t.eraserRadius, 0, Math.PI * 2);
t.cxt.strokeStyle = "rgba(250,250,250,0)";
t.cxt.fill();
t.cxt.globalCompositeOperation = "source-over"
},
hideColorSpan:function(){//隐藏颜色的选中状态
for(var i =0,length = this.colorSpan.length;i<length;i++){
this.colorSpan[i].style.display = 'none'
}
} };
paint.load();
</script>
</body>
</html>

  

H5网页涂鸦canvas的更多相关文章

  1. html2canvas 把h5网页保存为图片 区域保存

    html2canvas 把h5网页保存为图片 想把一个网页得某些元素,绘制成图片保存,有些数据是接口动态加载的,所以不能UI给到图片,需要我们把api的数据也绘制到图片上 html2canvas这个插 ...

  2. IOS 支付宝、微信回调传值给H5网页

    这里用是的苹果原生和JS的交互 .有不明白JavaScriptCore框架的可以去网上搜索下这方面的资料很多废话不多说直接上代码 @protocol JSContextDelegate <JSE ...

  3. 【微信H5支付】微信公众号里H5网页点击调取微信支付

    最近在公众号里开发了下单支付H5网页,需要在H5里调用微信支付界面.开发思路和代码整理如下: todo...

  4. 让人恼火的经历——手机H5网页被注入广告

    你的网站是否在尾部出现了让人恼火的广告? 这次我算是遇到了这些流氓的广告.那么就让我们一步步攻克这些恼火的广告吧. 问题描述 某一天下午开始,我们制作的网站就开始被各种广告注入,类似上图这种. 还有在 ...

  5. H5上传图片之canvas

    H5上传图片之canvas,使用canvas处理压缩图片再上传 html代码: <form action="" method="post"> < ...

  6. H5网页适配 iPhoneX,就是这么简单

    iPhoneX 取消了物理按键,改成底部小黑条,这一改动导致网页出现了比较尴尬的屏幕适配问题.对于网页而言,顶部(刘海部位)的适配问题浏览器已经做了处理,所以我们只需要关注底部与小黑条的适配问题即可( ...

  7. Android:webView加载h5网页视频,播放不了,以及横屏全屏的问题和实现自定义加载进度条的效果

    1.webView加载h5网页视频,播放不了,android3.0之后要在menifest添加硬件加速的属性 android:hardwareAccelerated="true". ...

  8. 如何将h5网页改成微信网页

    1.如何将h5网页改成微信网页 1.设置安全域名          先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”.         备注:登录后可在“开发者中心”查看对 ...

  9. chrome调试微信,app中H5网页的方法!

      调试微信,app中H5网页大概有如下几个方法: (1).我们可以直接把网页的url放在chrome浏览器中进行调试.(不涉及微信登录) (2).我们可以把网页的url放在微信开发者工具中进行调试. ...

随机推荐

  1. [HDU3518]Boring counting(后缀数组)

    传送门 求出现超过1次的不重叠子串的个数 根据论文中的方法. 枚举子串的长度 k. 用 k 给 height 数组分组,每一组求解,看看当前组的位置最靠后的后缀和位置最靠前的后缀所差个数是否大于长度, ...

  2. RestEasy+用户指南----第5章.@PathParam

    转载说明出处:http://blog.csdn.net/nndtdx/article/details/6870391 原文地址 http://docs.jboss.org/resteasy/docs/ ...

  3. Flume基本概念

    1         Apache Flume 1.1         概述 Flume是Cloudera提供的一个高可用,高可靠的,分布式的海量日志采集.聚合和传输的软件. Flume的核心是把数据从 ...

  4. dataguard switchover to physical stnadby

    首先做一系列的check check 当前primary 的 standby redo log是否存在 SQL> select * from v$logfile; GROUP# STATUS T ...

  5. Android:创建ZeroMQ的客户端

    这里我们将给出一个subscribe模式的客户端示例程序,如下: private class ZeroMQMessageTask extends AsyncTask<String, Void, ...

  6. Equals和==的差别

    java中的数据类型.可分为两类:  1.基本数据类型 包含:byte,short,char,int,long,float,double,boolean .基础数据类型比較大小的时候使用的是双等号(= ...

  7. Git使用SSH提交代码到server出现 permission denied (publickey).

    在GitBush中向已经存在的Repository提交README.md改动. 命令例如以下: touch README.md git init git add README.md git commi ...

  8. 自定cell(XIB)团购思路

    自定cell(XIB)团购思路 步骤一.先解析plist文件,创建model层数据. - (instancetype)initWithDict:(NSDictionary *)dict {     s ...

  9. Android之自己定义(上方标题随ViewPager手势慢慢滑动)

    近期非常蛋疼,项目要模仿网易新闻的样式去做.上次把仿网易新闻client的下拉刷新写出来了.这次是ViewPager的滑动,同一时候ViewPager的上面标题下划线尾随者移动.本来通过ViewPag ...

  10. 803E

    dp dp[i][j]表示到了i赢和输的差为j 如果这位是?向dp[i-1][j-1],dp[i-1][j],dp[i-1][j+1]转移,如果是W向dp[i-1][j-1]转移,如果是L向dp[i- ...