canvas画图--流畅没有齿痕的线,图像画线
画图,首先要获取鼠标位置,当鼠标在画图板上移动时,随之画线。
1.画图板canvas,监听鼠标事件
2.获取鼠标事件,得到鼠标位置。
var mouse = {x: 0, y: 0}; //起始鼠标位置,也就是mousedown var last_mouse = {x: 0, y: 0};/* Mouse Capturing Work */ canvas.addEventListener('mousemove', function(e) { last_mouse.x = mouse.x;last_mouse.y = mouse.y;mouse.x = e.pageX - this.offsetLeft; mouse.y = e.pageY - this.offsetTop; }, false);
以上,通过canvas.addEventListener使画图板canvas监听到鼠标事件。
3. 画线
var onPaint = function() {ctx.beginPath();ctx.moveTo(last_mouse.x, last_mouse.y); //moveTo 从一个点移动到另一个点。ctx.lineTo(mouse.x, mouse.y); //lineTo方法画直线; 方法接受终点的坐标(x,y)作为参数 ctx.closePath();ctx.stroke(); };
第一步是用 beginPath
创建一个路径。在内存里,路径是以一组子路径(直线,弧线等)的形式储存的,它们共同构成一个图形。每次调用 beginPath
,子路径组都会被重置,然后可以绘制新的图形。
第二步就是实际绘制路径的部分,moveTo和lineTo。
第三步是调用 closePath
方法,它会尝试用直线连接当前端点与起始端点来关闭路径,但如果图形已经关闭或者只有一个点,它会什么都不做。这一步不是必须的。
最后一步是调用 stroke
或 fill 方法,这时,图形才是实际的绘制到 canvas
上去。stroke
是绘制图形的边框,fill
会用填充出一个实心图形。
基础知识,请参考 https://developer.mozilla.org/zh-CN/docs/Canvas_tutorial/Drawing_shapes
以下是完整的代码。
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> 5 <meta http-equiv="Content-Script-Type" content="text/javascript" /> 6 <meta http-equiv="Content-Style-Type" content="text/css" /> 7 <meta name="viewport" content=" initial-scale=0.80,user-scalable=no" /> 8 <link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css" /> 9 <script src="http://code.jquery.com/jquery-1.8.2.js"></script> 10 <script src="http://code.jquery.com/ui/1.9.1/jquery-ui.js"></script> 11 <title>Pencil</title> 12 13 <style type="text/css"> 14 html, body {15 width: 100%; 16 height: 100%; 17 } 18 #sketch {19 border: 10px solid gray; 20 height: 100%; 21 position: relative; 22 } 23 #tmp_canvas {24 position: absolute; 25 left: 0px; right: 0; 26 bottom: 0; top: 0; 27 cursor: crosshair; 28 } 29 </style> 30 31 <script type="text/javascript"> 32 $(document).ready(function(){ 33 var canvas = document.querySelector('#paint'); 34 var ctx = canvas.getContext('2d'); 35 36 var sketch = document.querySelector('#sketch'); 37 var sketch_style = getComputedStyle(sketch); 38 canvas.width = parseInt(sketch_style.getPropertyValue('width')); 39 canvas.height = parseInt(sketch_style.getPropertyValue('height')); 40 41 var mouse = {x: 0, y: 0}; 42 var last_mouse = {x: 0, y: 0}; 43 44 /* Mouse Capturing Work */ 45 canvas.addEventListener('mousemove', function(e) { 46 last_mouse.x = mouse.x; 47 last_mouse.y = mouse.y; 48 49 mouse.x = e.pageX - this.offsetLeft; 50 mouse.y = e.pageY - this.offsetTop; 51 }, false); 52 53 54 /* Drawing on Paint App */ 55 ctx.lineWidth = 5; 56 ctx.lineJoin = 'round'; 57 ctx.lineCap = 'round'; 58 ctx.strokeStyle = 'blue'; 59 60 canvas.addEventListener('mousedown', function(e) { 61 canvas.addEventListener('mousemove', onPaint, false); 62 }, false); 63 64 canvas.addEventListener('mouseup', function() { 65 canvas.removeEventListener('mousemove', onPaint, false); 66 }, false); 67 68 var onPaint = function() { 69 ctx.beginPath(); 70 ctx.moveTo(last_mouse.x, last_mouse.y); 71 ctx.lineTo(mouse.x, mouse.y); 72 ctx.closePath(); 73 ctx.stroke(); 74 }; 75 }); 76 </script> 77 </head> 78 79 80 <body> 81 <div id="sketch"> 82 <canvas id="paint"></canvas> 83 </div> 84 85 </body> 86 </html>
这个代码很容易实现,但是它有个问题,就是画线不流畅,出现折断痕迹。
4.画流畅的线
可以根据二次贝塞尔曲线,连接2点画弧得到没有折痕的流畅曲线。
可以参照:
http://www.html5canvastutorials.com/labs/html5-canvas-modify-curves-with-anchor-points-using-kineticjs/
http://www.cartogrammar.com/blog/actionscript-curves-update/
1 tmp_ctx.beginPath(); 2 tmp_ctx.moveTo(ppts[0].x, ppts[0].y); //使用 beginPath() 和 moveTo() 方法来定义开始点 3 4 for (var i = 1; i < ppts.length - 2; i++) { 5 var c = (ppts[i].x + ppts[i + 1].x) / 2; 6 var d = (ppts[i].y + ppts[i + 1].y) / 2; 7 8 tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d); //二次贝塞曲线函数 9 } 10 11 // For the last 2 points 12 tmp_ctx.quadraticCurveTo( 13 ppts[i].x, 14 ppts[i].y, 15 ppts[i + 1].x, 16 ppts[i + 1].y 17 ); 18 tmp_ctx.stroke(); //这时,图形才是实际的绘制到 canvas 上去,stroke 是绘制图形的边框
quadraticCurveTo(cpx, cpy, x, y);方法通过使用表示二次贝塞尔曲线的指定控制点,向当前路径添加一个点。第一个点是用于二次贝塞尔计算中的控制点,第二个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。
虽然这样子可以画出贝塞尔曲线,但是你可以发现,它还是有锯齿边缘的。但是在画图之前加一个clearRect()函数,则锯齿消失!我不晓得这是为什么。。。
5.画没有齿痕的流畅曲线
tmp_ctx.beginPath(); tmp_ctx.moveTo(ppts[0].x, ppts[0].y); tmp_ctx.clearRect(0, 0, 2000, 2000);//它可以消除齿痕!for (var i = 1; i < ppts.length - 2; i++) {var c = (ppts[i].x + ppts[i + 1].x) / 2;var d = (ppts[i].y + ppts[i + 1].y) / 2;tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d); }// For the last 2 points tmp_ctx.quadraticCurveTo(ppts[i].x,ppts[i].y,ppts[i + 1].x,ppts[i + 1].y ); tmp_ctx.stroke();
6.接下来是橡皮的问题,虽然可以用相同背景色来代替,但是如果背景不单一,那就不管用了。所以,我们需要一个完完全全的橡皮,而不是相同背景,或者消除一块区域的痕迹。
那么,我们可以简单的引用globalCompositeOperation()函数,这个函数是用来在画布上组合颜色,我们可以利用这个原理,叠加(数学上的"或"原理)来制作橡皮。
同画笔一样,获得鼠标位置,叠加画板上已有的颜色,则为取消。
globalCompositeOperation()函数,请参考 http://www.html5canvastutorials.com/advanced/html5-canvas-global-composite-operations-tutorial/
画笔画图时: context.globalCompositeOperation = 'source-over'; //新的颜色覆盖之前的
橡皮擦除时: context.globalCompositeOperation = 'destination-out'; //新的颜色与之前颜色,重叠的部分消失
7. 画具有透明度的线
http://css.dzone.com/articles/sketching-html5-canvas-and
<!-- Internet Explorer 9、Firefox、Opera、Chrome 以及 Safari 支持。 From: http://www.cnblogs.com/muzijia/admin/EditPosts.aspx?postid=2841967--> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><meta content="text/html; charset=utf-8" http-equiv="Content-Type" /><meta http-equiv="Content-Script-Type" content="text/javascript" /><meta http-equiv="Content-Style-Type" content="text/css" /><meta name="viewport" content=" initial-scale=0.80,user-scalable=no" /><link rel="stylesheet" href="http://code.jquery.com/ui/1.9.1/themes/base/jquery-ui.css" /> <script src="http://code.jquery.com/jquery-1.8.2.js"></script><script src="http://code.jquery.com/ui/1.9.1/jquery-ui.js"></script><title>Pencil</title><style type="text/css">ul, li{clear:both;list-style:none;margin:0 auto;display: inline; }html, body {width: 100%;height: 100%;} #sketch {border: 10px solid gray;height: 100%;position: relative;}#tmp_canvas {position: absolute;left: 0px; right: 0;bottom: 0; top: 0;cursor: crosshair;}</style><script type="text/javascript">$(document).ready(function(){var canvas = document.querySelector('#paint');var ctx = canvas.getContext('2d');var sketch = document.querySelector('#sketch');var sketch_style = getComputedStyle(sketch);canvas.width = parseInt(sketch_style.getPropertyValue('width'));canvas.height = parseInt(sketch_style.getPropertyValue('height'));// Creating a tmp canvasvar tmp_canvas = document.createElement('canvas');var tmp_ctx = tmp_canvas.getContext('2d');tmp_canvas.id = 'tmp_canvas';tmp_canvas.width = canvas.width;tmp_canvas.height = canvas.height;sketch.appendChild(tmp_canvas);var mouse = {x: 0, y: 0};var last_mouse = {x: 0, y: 0};var paint = {init:function(canvasID_, canvas, context, brushImage){this.canvasID_ = canvasID_;this.canvasID = $("#"+canvasID_);this.canvas = canvas;this.context = context;/** Drawing on Line Paint App */this.context.lineWidth = 5;this.context.lineJoin = 'round';this.context.lineCap = 'round';this.context.strokeStyle = 'red';this.context.fillStyle = 'red'; this.color=["#000000","#9E9E9E","#FFFFFF","#8B5742","#FF0000","#FFC125","#00688B","#CDB38B","#CD8C95"]; this.lock = false; this.line = false; ppts = []; // Pencil Points this.brush = brushImage;this.context.globalAlpha = 1;/** mouse event */ if (this.touchSupported) {this.mouseDownEvent = "touchstart";this.mouseMoveEvent = "touchmove";this.mouseUpEvent = "touchend";}else {this.mouseDownEvent = "mousedown";this.mouseMoveEvent = "mousemove";this.mouseUpEvent = "mouseup";}this.bind();}, bind:function(){var t = this; //paint Instance this.canvasID.live({ mousedown: function(e){ mouse.x = typeof e.offsetX !== 'undefined' ? e.offsetX : e.layerX;mouse.y = typeof e.offsetY !== 'undefined' ? e.offsetY : e.layerY;ppts.push({x: mouse.x , y: mouse.y}); t.lock=true;},mousemove: function(e){ if(t.lock){ mouse.x = typeof e.offsetX !== 'undefined' ? e.offsetX : e.layerX;mouse.y = typeof e.offsetY !== 'undefined' ? e.offsetY : e.layerY; ppts.push({x: mouse.x , y: mouse.y });//tmp_ctx.clearRect(0, 0, 2000, 2000);//if(t.line == true){ //draw line t.onPaint(); //} //if(t.line ==false){//t.drawPoint(); //draw image //} } },mouseleave:function(e){t.lock = false; //ctx.drawImage(tmp_canvas, 0, 0);//tmp_ctx.clearRect(0, 0, 2000, 2000); ppts = [];},mouseup: function(e){ t.lock = false; //ctx.drawImage(tmp_canvas, 0, 0);//tmp_ctx.clearRect(0, 0, 2000, 2000); //tmp_ctx.drawImage(canvas, 0, 0); ppts = []; }}); },onPaint:function() {var tmp_ctx = this.context; // Tmp canvas is always cleared up before drawing. tmp_ctx.clearRect(0, 0, 2000, 2000); //取消齿痕; 如果想用橡皮,则注释这句,因为绘图痕迹绘在两个图层中。 if (ppts.length < 3) {var b = ppts[0];tmp_ctx.beginPath();tmp_ctx.arc(b.x, b.y, tmp_ctx.lineWidth / 2, 0, Math.PI * 2, !0);tmp_ctx.fill();tmp_ctx.closePath();return;} tmp_ctx.beginPath();tmp_ctx.moveTo(ppts[0].x, ppts[0].y);for (var i = 1; i < ppts.length - 2; i++) {var c = (ppts[i].x + ppts[i + 1].x) / 2;var d = (ppts[i].y + ppts[i + 1].y) / 2; tmp_ctx.quadraticCurveTo(ppts[i].x, ppts[i].y, c, d); }// For the last 2 points tmp_ctx.quadraticCurveTo(ppts[i].x,ppts[i].y,ppts[i + 1].x,ppts[i + 1].y); tmp_ctx.stroke(); },changeColor:function(style,color){ var t=this;var styleNum = style;var colorNum = color; console.debug("pen ="+style+", color="+color);t.context.strokeStyle = t.color[colorNum];t.context.fillStyle = t.color[colorNum]; if(styleNum == 0){ //mark pen t.line = true; t.context.lineWidth = 30;t.context.globalAlpha = 0.5;t.context.globalCompositeOperation = 'source-over'; console.debug("mark"); }if(styleNum == 1){ //peicnl t.line = true; t.context.lineWidth = 5;t.context.globalAlpha = 1; t.context.globalCompositeOperation = 'source-over'; console.debug("pencil"); }if(styleNum == 2){ //resetEraser t.line = true; //t.context = ctx; t.resetEraser();} },resetEraser:function(){ var t=this; //t.context = ctx; t.context.lineWidth = 30;t.context.globalAlpha = 1;t.context.globalCompositeOperation = 'destination-out';console.debug("resetEraser");},clear:function(){ppts = [];this.context.globalAlpha = 0;this.context.clearRect(0, 0, this.w, this.h);}};<!-- drawing -->var brush = new Image(); brush.src = "images/color_01.png"; //defalut red brush.onload = function(){ paint.init('tmp_canvas',tmp_canvas,tmp_ctx, brush); };var style = 1;var color = 1; $('.tool> li > a').click(function() { var idx = $('.tool> li > a').index(this); style = idx;paint.changeColor(style, color); if(idx == 2){//paint.init('paint',paint,ctx, brush); }});$('.brush > li > a').click(function() { var idx = $('.brush > li > a').index(this); var i = idx + 1;//brush.src = "images/color_0"+i+".png"; color = idx;paint.changeColor(style, color); });});</script> </head><body><div class="pencil"> <ul class="tool"> <li><a class="btn_pen" href="javascript:void(0)"><img src="data:images/crayon-outline.png" alt=""></a></li> <li><a class="btn_mark" href="javascript:void(0)"><img src="data:images/marker-outline.png" alt=""></a></li> <li><a class="btn_eraser" href="javascript:void(0)"><img src="data:images/eraser-outline.png" alt=""></a></li> <li><a class="btn_mark" href="javascript:void(0)"><img src="data:images/image-outline.png" alt=""></a></li> </ul><ul class="brush"><li><a href="javascript: void(0);"><img src="data:images/color_01.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_02.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_03.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_04.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_05.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_06.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_07.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_08.png" /></a></li><li><a href="javascript: void(0);"><img src="data:images/color_09.png" /></a></li></ul> </div><div id="sketch"><canvas id="paint"></canvas></div></body> </html>
转载于:https://www.cnblogs.com/nlyangtong/p/10033045.html
canvas画图--流畅没有齿痕的线,图像画线相关推荐
- Android在图片画线(放大,旋转,平移后可继续正确画线,限制画线区域)
最近因为公司业务需求,需要给学校的老师们做一个在手机和电脑上同步进行图片上画线批注的效果.刚开始在github上看了几天, 但跟我们要求吻合的开源项目几乎没有.最后只能自己来实现一个相应的功能,经过一 ...
- Android动态画线 坐标画线动画
效果图如下 根据相对于图片本身的坐标xy数组 基于view的左上角为原点 在图片上动态画线 //参考数据类型//pointList [PointEntity(pointX=1, pointY=1), ...
- html5画图论文结束语,基于HTML5 Canvas画图软件的设计与实现.doc
摘要:在最近十年里,HTML5在Web开发标准完成了巨大的飞跃,和以前的版本相比,HTML5不但用来表示Web的内容,而且还把Web带入一个更高的平台.HTML5为我们带来很多新的特性,其中一个最重要 ...
- 路径图形html5 Canvas画图2:画线条 -java教程
空话就不多说了,开始... 如果你还不道知Canvas是什么,可以看看上一篇. 在学画画的时候,线条是最基本的了,而线条的接连可以成组任何图形.在Canvas中也是如此. 在开始之前我们先拿出画布和画 ...
- Canvas - 画线
文章目录 画线 使用鼠标画线 参考 画线 <!DOCTYPE html> <html><head><meta charset="utf-8" ...
- excel部分网格线不见了_画线的工具和使用法,变换网格线的式样,画线对作品效果的影响...
黄简讲书法:四级课程(格式篇)27--画线 一 画线的工具 前两堂说了,写书法作品时经常用线来定位.线有两种:一是临时的,折线就是这一种,另一种是永久的,那是用颜色画在纸面上的线,是我们想把它保留在作 ...
- OpenCV:Mat数据类型/16to8bit/RECT/画线填充
Mat类型与数据类型对应关系: Unsigned 8bits uchar 0~255 Mat: CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4 Signed 8bits char ...
- Unity实用案例之——屏幕画线和线框渲染
游戏里经常会遇到各种画线的需求,今天我们利用GL来实现其中的两个画线功能. 一.屏幕画线 屏幕画线是一种很好的用户交互方式,通过屏幕画线可以控制游戏中的各种元素,Unity提供了UnityEnige. ...
- Unity中在Game窗口画线
在Unity中画线有几种方式: Debug.DrawLine() 函数画线,在Game窗口不开启 Gizmos 时,只在Scene窗口显示,多用于调试. 通过 LineRenderer 来画线, ...
最新文章
- 石头剪刀布python代码_我的第一个python程序,石头剪刀布猜拳游戏
- Android7.0 PowerManagerService(3) 核心函数updatePowerStateLocked的主要流程
- 毕业与计算机专业,电子与计算机工程专业毕业后干什么
- python——实现简单的强化学习
- 吴恩达深度学习4.2笔记_Convolutional Neural Networks_深度卷积模型
- 计算机网络 间接路由选择与直接路由选择
- php7.0-fpm.sock
- 137_原始套接字_发送UDP数据,模仿他人飞秋给另一个飞秋客户端发送信息
- matlab的开方算法_matlab最大公约数 三种算法
- 【产品】 产品设计:ID工业设计、MD结构设计、HW硬件设计和SW软件设计详解
- MarkDown基本语法(标题,字体,引用,分割线、插入图片,超链接,列表,表格,插入代码标段)
- b2b2c o2o 多商家入驻商城 直播带货商城 电子商务
- 怎么退出自适应巡航_自适应巡航功能是何方神圣?“全速域自适应巡航”又有什么作用呢...
- Echarts点击事件
- 前端面试题精选(3)
- 新松机器人socket_谈谈本人对新松的印象,给后辈们一点启示
- Google Earth选项中的重要设置
- Maya 凹凸贴图与置换贴图
- PCB板用基板材料分类
- 经验模态分解python_如何提高希尔伯特黄变换中经验模态分解(EMD)的速度?