javascript结合html5 canvas实现(可调画笔颜色/粗细/橡皮)的涂鸦板


Posted in Javascript onApril 27, 2013

js+html5 canvas实现的涂鸦画板特效,可调画笔颜色|粗细|橡皮,可以保存涂鸦效果为图片编码,非常适合学习html5的canvas,必须支持html5的浏览器才能看到效果。

<!doctype html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
<title>javascript结合html5 canvas实现的涂鸦板 - 分享JavaScript-sharejs.com</title> 
<meta name="Copyright" content="JavaScript分享网 http://www.sharejs.com/" /> 
<meta name="description" content="javascript结合html5 canvas实现的涂鸦板,JavaScript分享网,js脚本,网页特效,网页模板,png图标,矢量图下载" /> 
<meta content="JavaScript,分享,JavaScript代码,Ajax,jQuery,网页模板,PNG图标,矢量图" name="keywords" /> 
</head> 
<body> 
<style> 
*{margin:0;padding:0;} 
.fa{width:740px;margin:0 auto;} 
.top{margin:20px 0;} 
.top input{width:25px;height:25px;border:1px solid #fff;border-radius:4px;background:#ddd;} 
.top .i1{background:#000000;} 
.top .i2{background:#FF0000;} 
.top .i3{background:#80FF00;} 
.top .i4{background:#00FFFF;} 
.top .i5{background:#808080;} 
.top .i6{background:#FF8000;} 
.top .i7{background:#408080;} 
.top .i8{background:#8000FF;} 
.top .i9{background:#CCCC00;} 
#canvas{background:#eee;cursor:default;} 
.font input{font-size:14px;} 
.top .grea{background:#aaa;} 
</style> 
</head> 
<body> 
<div class="fa"> 
<div class="top"> 
<div id="color"> 
请选择画笔颜色: 
<input class="i1" type="button" value="" /> 
<input class="i2" type="button" value="" /> 
<input class="i3" type="button" value="" /> 
<input class="i4" type="button" value="" /> 
<input class="i5" type="button" value="" /> 
<input class="i6" type="button" value="" /> 
<input class="i7" type="button" value="" /> 
<input class="i8" type="button" value="" /> 
<input class="i9" type="button" value="" /> 
</div> 
<div class="font" id="font"> 
请选择画笔的宽度: 
<input type="button" value="细" /> 
<input type="button" value="中" class="grea"/> 
<input type="button" value="粗" /> 
</div> 
<div> 
<span id="error">如果有错误,请使用橡皮擦:</span> 
<input id="eraser" style="width:60px;font-size:14px;"type="button" value="橡皮擦" /> 
</div> 
<input id="clear" type="button" value="清除画布" style="width:80px;"/> 
<input id="revocation" type="button" value="撤销" style="width:80px;"/> 
<input id="imgurl" type="button" value="导出图片路径" style="width:80px;"/> 
</div> 
<canvas id="canvas" width="740" height="420">您的浏览器不支持 canvas 标签</canvas> 
<div id="div1"></div> 
</div> 
<div id="html"> 
</div> 
<script> 
(function(){ 
var paint={ 
init:function() 
{ 
this.load(); 
}, 
load:function() 
{ 
this.x=[];//记录鼠标移动是的X坐标 
this.y=[];//记录鼠标移动是的Y坐标 
this.clickDrag=[]; 
this.lock=false;//鼠标移动前,判断鼠标是否按下 
this.isEraser=false; 
//this.Timer=null;//橡皮擦启动计时器 
//this.radius=5; 
this.storageColor="#000000"; 
this.eraserRadius=15;//擦除半径值 
this.color=["#000000","#FF0000","#80FF00","#00FFFF","#808080","#FF8000","#408080","#8000FF","#CCCC00"];//画笔颜色值 
this.fontWeight=[2,5,8]; 
this.$=function(id){return typeof id=="string"?document.getElementById(id):id;}; 
this.canvas=this.$("canvas"); 
if (this.canvas.getContext) { 
} else { 
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.imgurl=this.$("imgurl");//图片路径按钮 
this.w=this.canvas.width;//取画布的宽 
this.h=this.canvas.height;//取画布的高 
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.iptClear.onclick=function() 
{ 
t.clear(); 
}; 
/*鼠标按下事件,记录鼠标位置,并绘制,解锁lock,打开mousemove事件*/ 
this.canvas['on'+t.StartEvent]=function(e) 
{ 
var touch=t.touch ? e.touches[0] : e; 
var _x=touch.clientX - touch.target.offsetLeft;//鼠标在画布上的x坐标,以画布左上角为起点 
var _y=touch.clientY - touch.target.offsetTop;//鼠标在画布上的y坐标,以画布左上角为起点 
if(t.isEraser) 
{ 
/* 
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"; 
*/ 
t.resetEraser(_x,_y,touch); 
}else 
{ 
t.movePoint(_x,_y);//记录鼠标位置 
t.drawPoint();//绘制路线 
} 
t.lock=true; 
}; 
/*鼠标移动事件*/ 
this.canvas['on'+t.MoveEvent]=function(e) 
{ 
var touch=t.touch ? e.touches[0] : e; 
if(t.lock)//t.lock为true则执行 
{ 
var _x=touch.clientX - touch.target.offsetLeft;//鼠标在画布上的x坐标,以画布左上角为起点 
var _y=touch.clientY - touch.target.offsetTop;//鼠标在画布上的y坐标,以画布左上角为起点 
if(t.isEraser) 
{ 
//if(t.Timer)clearInterval(t.Timer); 
//t.Timer=setInterval(function(){ 
t.resetEraser(_x,_y,touch); 
//},10); 
} 
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() 
{ 
t.redraw(); 
}; 
this.changeColor(); 
this.imgurl.onclick=function() 
{ 
t.getUrl(); 
}; 
/*橡皮擦*/ 
this.$("eraser").onclick=function(e) 
{ 
t.isEraser=true; 
t.$("error").style.color="red"; 
t.$("error").innerHTML="您已使用橡皮擦!"; 
}; 
}, 
movePoint:function(x,y,dragging) 
{ 
/*将鼠标坐标添加到各自对应的数组里*/ 
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() , 绘制当前路径 
} 
}, 
clear:function() 
{ 
this.cxt.clearRect(0, 0, this.w, this.h);//清除画布,左上角为起点 
}, 
redraw:function() 
{ 
/*撤销*/ 
this.cxt.restore(); 
}, 
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("input"),fontIptNum=this.$("font").getElementsByTagName("input"); 
for(var i=0,l=iptNum.length;i<l;i++) 
{ 
iptNum[i].index=i; 
iptNum[i].onclick=function() 
{ 
t.cxt.save(); 
t.cxt.strokeStyle = t.color[this.index]; 
t.storageColor=t.color[this.index]; 
t.$("error").style.color="#000"; 
t.$("error").innerHTML="如果有错误,请使用橡皮擦:"; 
t.cxt.strokeStyle = t.storageColor; 
t.isEraser=false; 
} 
} 
for(var i=0,l=fontIptNum.length;i<l;i++) 
{ 
t.cxt.save(); 
fontIptNum[i].index=i; 
fontIptNum[i].onclick=function() 
{ 
t.changeBackground(this.index); 
t.cxt.lineWidth = t.fontWeight[this.index]; 
t.$("error").style.color="#000"; 
t.$("error").innerHTML="如果有错误,请使用橡皮擦:"; 
t.isEraser=false; 
t.cxt.strokeStyle = t.storageColor; 
} 
} 
}, 
changeBackground:function(num) 
{ 
/*添加画笔粗细的提示背景颜色切换,灰色为当前*/ 
var fontIptNum=this.$("font").getElementsByTagName("input"); 
for(var j=0,m=fontIptNum.length;j<m;j++) 
{ 
fontIptNum[j].className=""; 
if(j==num) fontIptNum[j].className="grea"; 
} 
}, 
getUrl:function() 
{ 
this.$("html").innerHTML=this.canvas.toDataURL(); 
}, 
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" 
} 
}; 
paint.init(); 
})(); 
</script> 
<div style="clear:both"></div> 
</body> 
</html>
Javascript 相关文章推荐
JS拖动技术 关于setCapture使用
Dec 09 Javascript
原生JS实现响应式瀑布流布局
Apr 02 Javascript
JS随机调用指定函数的方法
Jul 01 Javascript
详细谈谈javascript的对象
Jul 31 Javascript
js css3实现图片拖拽效果
Mar 04 Javascript
JavaScript实现body内任意节点的自定义属性功能示例
Sep 18 Javascript
JavaScript判断变量名是否存在数组中的实例
Dec 28 Javascript
浅谈vue引用静态资源需要注意的事项
Sep 28 Javascript
使用iView Upload 组件实现手动上传图片的示例代码
Oct 01 Javascript
小程序如何构建骨架屏
May 29 Javascript
如何使用webpack打包一个库library的方法步骤
Dec 18 Javascript
vue中div禁止点击事件的实现
Apr 02 Vue.js
jQuery语法高亮插件支持各种程序源代码语法着色加亮
Apr 27 #Javascript
JQuery onload、ready概念介绍及使用方法
Apr 27 #Javascript
用jquery实现输入框获取焦点消失文字
Apr 27 #Javascript
javascript中强制执行toString()具体实现
Apr 27 #Javascript
用客户端js实现带省略号的分页
Apr 27 #Javascript
jquery ajax同步异步的执行最终解决方案
Apr 26 #Javascript
html中使用javascript调用本地程序(exe、doc等)实现代码
Apr 26 #Javascript
You might like
php摘要生成函数(无乱码)
2012/02/04 PHP
如何解决CI框架的Disallowed Key Characters错误提示
2013/07/05 PHP
PHP处理JSON字符串key缺少双引号的解决方法
2014/09/16 PHP
php循环table实现一行两列显示的方法
2015/06/04 PHP
PHP实现的自定义数组排序函数与排序类示例
2016/11/18 PHP
PHP/HTML混写的四种方式总结
2017/02/27 PHP
Node.js中创建和管理外部进程详解
2014/08/16 Javascript
EasyUI中datagrid在ie下reload失败解决方案
2015/03/09 Javascript
jQuery自动完成插件completer附源码下载
2016/01/04 Javascript
原生javascript实现解析XML文档与字符串
2016/03/01 Javascript
简洁实用的BootStrap jQuery手风琴插件
2016/08/31 Javascript
js仿网易表单及时验证功能
2017/03/07 Javascript
ejsExcel模板在Vue.js项目中的实际运用
2018/01/27 Javascript
vue axios封装httpjs,接口公用配置拦截操作
2020/08/11 Javascript
Vue页面渲染中key的应用实例教程
2021/01/12 Vue.js
nestjs中异常过滤器Exceptionfilter的具体使用
2021/02/07 Javascript
[01:14:41]DOTA2-DPC中国联赛定级赛 iG vs Magma BO3第一场 1月8日
2021/03/11 DOTA
python连接mysql数据库示例(做增删改操作)
2013/12/31 Python
利用Psyco提升Python运行速度
2014/12/24 Python
python threading模块操作多线程介绍
2015/04/08 Python
Python爬取国外天气预报网站的方法
2015/07/10 Python
python读取TXT每行,并存到LIST中的方法
2018/10/26 Python
python合并已经存在的sheet数据到新sheet的方法
2018/12/11 Python
python实现操作文件(文件夹)
2019/10/31 Python
python虚拟环境模块venv使用及示例
2020/03/04 Python
python dict如何定义
2020/09/02 Python
结合 CSS3 transition transform 实现简单的跑马灯效果的示例
2018/02/07 HTML / CSS
波兰最大的度假胜地和城市公寓租赁运营商:Sun & Snow
2018/10/18 全球购物
澳大利亚天然护肤品、化妆品和健康产品一站式商店:Nourished Life
2018/12/02 全球购物
咖啡店自主创业商业计划书
2014/01/22 职场文书
室内设计专业毕业生求职信
2014/05/02 职场文书
根叔历年演讲稿
2014/05/20 职场文书
机关干部作风建设剖析材料
2014/10/23 职场文书
学术会议邀请函
2015/01/30 职场文书
2015年村级财务管理制度
2015/08/04 职场文书
在Windows下安装配置CPU版的PyTorch的方法
2021/04/02 Python