html5 canvas实现的手机端签字板
2015-10-28 00:00
411 查看
摘要: 可以实现手机端手指的签字,撤销,保存为图片以及重写等操作
功能展示:
这里显示不了图片,就算了吧。。。。
功能具体实现:
参数配置:
var DEFAULT_BRUSH_SIZE = 3;//设置画笔的粗细
var DEFAULT_BRUSH_COLOR = "#000000";//设置画笔的颜色
var BACKGROUND_COLOR = "#FFFFFF";//设置画布的背景颜色
var cut = 0;//设置断点
var point = {};//记录画笔的位置
var next_point = {};//记录下一个画笔的位置
var context;//context上下文
其中说明下context上下文的作用:html5中canvas本身是不具有绘画功能的,就是一个画布,类似于Java中的一个panel,而context可以提供在画布中绘画的方法和属性,通过canvas.getContext()得到
补充一点:因为是实现签字功能,其实就是实现两点之间画直线,需要一个起始点和一个终点,也就是上面参数设置的:point和next_point
这里我们需要不断的监控point和next_point的变化:
首先设置x和y的坐标:
因为要不断的监控坐标的变化,这里我另外封装了一个方法,一遍调用它(其实后来我在想,为什么要另外封装一个方法,不能直接调用呢?\(^o^)/)
调用如下:
下面是初始化画布和画笔的操作:
默认的第一个点为(0,0)其中需要说明的就是setInterval()方法,这个就是实现了不断地调用,一旦启动,就会不停的调用
clearInterval(setInterval(function,time))这个方法
因为是手机端,所以在上面注册touchmove、touchstart、touchend方法
下面是绘图的方法:
下面是对应的touchmove,touchstart,touchend方法
其中需要注意点是断点连续的问题:
这一笔画完,和下一笔开始时,首尾链接到一起去了
所以这里我的处理方法是:】
设置一个cut断点,开始触发时,把断点设为1;在draw方法中判断断点,如果断点为1则不执行任何操作,touchmove方法中让断点累加
这样就实现了基本的签字功能
撤销功能:
Canvas中有一个restore方法,可以返回到save操作的那个状态,然而我使用的时候并没有什么卵用 (*  ̄︿ ̄)
解决方案:
因为canvas是透明的!!!这就联想到ps中图层的效果,最终展现的时候是每个图层的叠加,
每touchstart的时候就新建一个图层(<canvas>)
实现:
注意新建的<canvas>,html中是以堆栈管理的,所以删除应该是删除最上面的一个图层
所以重画 也就非常简单了:不断地调用撤销操作:
这里貌似我写的有些复杂,让撤销调用了重画的方法,其实代码可以简化下的o(一︿一+)o
保存的时候有些麻烦:需要将每一个图层(下面就用图层来代替canvas)合并为一个图层,又类似ps中的图层合并
思想就是调用context中的drawImage方法,图层绘画图层,但是后来发现绘画玩,底层的图层和上面的图层就有很多的重合,撤销和重画功能都不灵了,具体的解决步骤如下:
其中需要说明下的就是context中的toDataURL();默认转成png格式的,当然也可以自己指定,在toDataURL中加上参数即可
网上都有说要base64.js和canvas2image.js,才能转成图片保存,当然我也下载了,当时后来我把两个引入注释掉,貌似功能并没有收到影响 O(∩_∩)O哈哈~
功能展示:
这里显示不了图片,就算了吧。。。。
功能具体实现:
参数配置:
var DEFAULT_BRUSH_SIZE = 3;//设置画笔的粗细
var DEFAULT_BRUSH_COLOR = "#000000";//设置画笔的颜色
var BACKGROUND_COLOR = "#FFFFFF";//设置画布的背景颜色
var cut = 0;//设置断点
var point = {};//记录画笔的位置
var next_point = {};//记录下一个画笔的位置
var context;//context上下文
其中说明下context上下文的作用:html5中canvas本身是不具有绘画功能的,就是一个画布,类似于Java中的一个panel,而context可以提供在画布中绘画的方法和属性,通过canvas.getContext()得到
补充一点:因为是实现签字功能,其实就是实现两点之间画直线,需要一个起始点和一个终点,也就是上面参数设置的:point和next_point
这里我们需要不断的监控point和next_point的变化:
首先设置x和y的坐标:
function setPoint(x, y) { //不断执行 var n_point = {}; n_point.x = x; n_point.y = y; return n_point; }
function upDate(up_point) { //不断执行 if (!next_point) { next_point = setPoint(0, 0); } else { next_point = setPoint(up_point.x, up_point.y); } }
因为要不断的监控坐标的变化,这里我另外封装了一个方法,一遍调用它(其实后来我在想,为什么要另外封装一个方法,不能直接调用呢?\(^o^)/)
调用如下:
function loop(e) { upDate(point); }
下面是初始化画布和画笔的操作:
function init() { var canvas = document.getElementById("canvas"); var canvasWidth = canvas.width = window.innerWidth;//获取画布的宽度 var canvasHeight = canvas.height = window.innerHeight;//获取画布的高度 context = canvas.getContext('2d');//获取画布上下文 context.fillStyle = BACKGROUND_COLOR;//设置背景填充颜色 context.fillRect(0, 0, canvasWidth, canvasHeight);//设置画布背景 point.x = 0; point.y = 0; canvas.addEventListener('touchmove', touchMove, false); canvas.addEventListener('touchstart', touchStart, false); canvas.addEventListener('touchend', touchEnd, false); document.getElementById("chonghua").addEventListener('click', chonghua, false); document.getElementById('backButton').addEventListener('click', backAction, false); setInterval(loop, 1); }
默认的第一个点为(0,0)其中需要说明的就是setInterval()方法,这个就是实现了不断地调用,一旦启动,就会不停的调用
clearInterval(setInterval(function,time))这个方法
因为是手机端,所以在上面注册touchmove、touchstart、touchend方法
下面是绘图的方法:
function draw(context) { if (cut > 1) { //context.save;//保存当前绘画状态 context.fillStyle = DEFAULT_BRUSH_COLOR;//设置填充的背景颜色 context.lineWidth = DEFAULT_BRUSH_SIZE;//设置画笔的大小 context.lineCap = "tound";//设置线条,让线条更加的圆润 context.beginPath(); context.moveTo(point.x, point.y); context.lineTo(next_point.x, next_point.y); console.log("画笔" + cut); context.stroke(); context.restore();//回复绘画状态 } }
下面是对应的touchmove,touchstart,touchend方法
//触摸滑动事件 function touchMove() { var e = event.touches[0]; console.log("touchMove"); point = setPoint(e.clientX, e.clientY); $pos_display.innerHTML = '你上一点鼠标的位置为(' + point.x + ',' + point.x + ').<br/>你当前鼠标的位置为(' + next_point.x + ',' + next_point.x + ')';//更新当前鼠标点击的位置 draw(context); cut++; }
//触摸开始事件 function touchStart() { console.log("touchStart"); var canvas = document.createElement('canvas'); var content = document.getElementById('canvasContent'); content.appendChild(canvas); canvas.width = window.innerWidth; canvas.height = window.innerHeight; canvas.addEventListener('touchmove', touchMove, false); canvas.addEventListener('touchstart', touchStart, false); canvas.addEventListener('touchend', touchEnd, false); context = canvas.getContext('2d'); draw(context); cut = 1; }
//触摸结束时间 function touchEnd() { console.log("touchEnd"); document.getElementById("canvas").getContext('2d').save(); }
其中需要注意点是断点连续的问题:
这一笔画完,和下一笔开始时,首尾链接到一起去了
所以这里我的处理方法是:】
设置一个cut断点,开始触发时,把断点设为1;在draw方法中判断断点,如果断点为1则不执行任何操作,touchmove方法中让断点累加
这样就实现了基本的签字功能
撤销功能:
Canvas中有一个restore方法,可以返回到save操作的那个状态,然而我使用的时候并没有什么卵用 (*  ̄︿ ̄)
解决方案:
因为canvas是透明的!!!这就联想到ps中图层的效果,最终展现的时候是每个图层的叠加,
每touchstart的时候就新建一个图层(<canvas>)
实现:
//撤销上一次操作 function backAction() { console.log(document.getElementsByTagName("canvas").length); if (document.getElementsByTagName("canvas").length == 1) { chonghua(); }else{ document.getElementById('canvasContent').removeChild(document.getElementsByTagName("canvas")[document.getElementsByTagName("canvas").length - 1]); } }
注意新建的<canvas>,html中是以堆栈管理的,所以删除应该是删除最上面的一个图层
所以重画 也就非常简单了:不断地调用撤销操作:
//重画 function chonghua() { var max = document.getElementsByTagName("canvas").length-1; for(var i = max;i>0;i--){ document.getElementById('canvasContent').removeChild(document.getElementsByTagName("canvas")[document.getElementsByTagName("canvas").length - 1]); } if(document.getElementsByTagName("canvas").length == 1){ var context = document.getElementById('canvas').getContext('2d'); context.fillStyle = "#ffffff"; context.fillRect(0,0,window.innerWidth,window.innerHeight); }; }
这里貌似我写的有些复杂,让撤销调用了重画的方法,其实代码可以简化下的o(一︿一+)o
保存的时候有些麻烦:需要将每一个图层(下面就用图层来代替canvas)合并为一个图层,又类似ps中的图层合并
思想就是调用context中的drawImage方法,图层绘画图层,但是后来发现绘画玩,底层的图层和上面的图层就有很多的重合,撤销和重画功能都不灵了,具体的解决步骤如下:
function drawImg(img){ var canvas = document.getElementById("canvas"); return canvas.getContext('2d').drawImage(img,0,0); }
$scope.saveImg = function () { var canvas = document.getElementById("canvas"); var canvasLength = document.getElementsByTagName("canvas").length-1; for(var i = canvasLength;i>0;i--){ drawImg(document.getElementsByTagName("canvas")[i]); document.getElementById("canvasContent").removeChild(document.getElementsByTagName("canvas")[i]) } var dataUrl = canvas.toDataURL(); $scope.globalNavigator.pushPage('main/crm/img.html', { animation: "fade", src: dataUrl }) }
其中需要说明下的就是context中的toDataURL();默认转成png格式的,当然也可以自己指定,在toDataURL中加上参数即可
网上都有说要base64.js和canvas2image.js,才能转成图片保存,当然我也下载了,当时后来我把两个引入注释掉,貌似功能并没有收到影响 O(∩_∩)O哈哈~
相关文章推荐
- Android dp2px
- android资讯类软件框架
- 怎样用MindMapper中的色彩来装饰主题背景
- 苏州实时公交app接口根据站台查询公交状态
- iOS 给服务器发送Json数据demo
- iOS NSTimer样例demo
- IOS横竖屏
- IOS 修改工程名称,项目名称
- IOS scrollView 知识点
- 关于Android组件通信的理解
- Android(5)多选按钮CheckBox、OnClickListener、OnCheckedChangeListener
- springMVC配置一个通配的url请求,替代@RequestMapping中指定的方式
- 【转】android布局属性详解
- codeforces#292B_Drazil and His Happy Friends-暴力水题
- android 62 手机存储目录的划分
- 【转】Android开发学习笔记:5大布局方式详解
- 【优雅代码】深入浅出 妙用Javascript中apply、call、bind
- cocos2dx3.8指导教程
- Android学习之Activity的四种启动模式与特点
- android实现画板功能