这篇文章主要介绍了在html5中怎么使用canvas画板实现平滑曲线,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。

功能需求

项目需求:需要实现一个可以自由书写的小画板

简单实现

对于熟悉canvas的同学来说,这个需求很简单,大致逻辑如下:

1)监听事件pointerdown,pointermove,pointerup

2)标记是否拖拽画线模式变量 isDrawing,在down事件时置为true,up的时候置为false

3)使用canvas的api,设置线条样式,调用绘制线条接口lineTo方法

短短几十行代码就能实现:

<!doctypehtml><html><head><metacharset=utf-8><style>canvas{border:1pxsolid#ccc}body{margin:0;}</style></head><body><canvasid="c"width="1920"height="1080"></canvas><script>varel=document.getElementById('c');varctx=el.getContext('2d');//设置绘制线条样式ctx.strokeStyle='red';ctx.lineWidth=1;ctx.lineJoin='round';ctx.lineCap='round';varisDrawing;//标记是否要绘制//存储坐标点letlastX,lastY;document.body.onpointerdown=function(e){console.log('pointerdown');isDrawing=true;lastX=e.clientX;lastY=e.clientY;};document.body.onpointermove=function(e){console.log('pointermove');if(isDrawing){draw(e.clientX,e.clientY,lastX,lastY);}lastX=e.clientX,lastY=e.clientY;};document.body.onpointerup=function(e){if(isDrawing){draw(e.clientX,e.clientY,lastX,lastY);}lastX=e.clientX,lastY=e.clientY;isDrawing=false;};functiondraw(x,y,lastX,lastY){ctx.beginPath();ctx.moveTo(lastX,lastY);ctx.lineTo(x,y);ctx.stroke();}</script></body></html>

实现效果如下图:

以上就简单的实现了画板功能,如果要求不高的用户可以使用,但一旦遇到有点要求的用户就无法交付这种产品,仔细看是线条折线感太强。

为什么会有折线感呢?

主要原因:

我们调用的api方法lineTo是两点连线也就是直线

浏览器对鼠标事件mousemove的采集是有采集频率的,并不是每个鼠标移动经过的每一个像素点都会触发事件。

当鼠标移动的越快,那么两点之间的间隔就越远,那么折线感就更明显。

如何能绘制平滑的曲线?

canvas提供的api中是有现成接口的,贝塞尔系列的接口就能满足我们的要求,接下来我们讲一下使用二次贝塞尔曲线绘制平滑曲线。

quadraticCurveTo(cpx,cpy,x,y)

二次贝塞尔曲线接口需要四个参数,cpx,cpy是曲线的控制点,x,y是曲线终点。

有人问那曲线的起点在哪里?其实曲线的起点取决于上一操作状态,可以是moveTo的位置,或者是lineTo的位置,或者是贝塞尔的终点。

那么怎么调用quadraticCurveTo,参数怎么传呢?

我们需要找出关键位置,直接用例子告诉大家吧

1)假如我们用鼠标采集到ABCDEF六个点

2)取前面三个点ABC计算,BC的中点B1,以A为起点,B为控制点,B1为终点,那么利用quadraticCurveTo可以绘制出这样一条贝塞尔曲线

3)接下来计算CD的中点C1,以B1为起点,C为控制点,C1为终点,那么利用quadraticCurveTo可以绘制出这样一条贝塞尔曲线

4)以此类推,当到了最后一个点时以D1为起点,E为控制点,F为终点,结束贝塞尔绘制。

根据算法进行代码改造

OK我们介绍了具体算法的影响,那用该算法对我们前面的代码进行改造:

<!doctypehtml><html><head><metacharset=utf-8><style>canvas{border:1pxsolid#ccc}body{margin:0;}</style></head><body><canvasid="c"width="1920"height="1080"></canvas><script>varel=document.getElementById('c');varctx=el.getContext('2d');//设置绘制线条样式ctx.strokeStyle='red';ctx.lineWidth=1;ctx.lineJoin='round';ctx.lineCap='round';varisDrawing;//标记是否要绘制//存储坐标点letpoints=[];document.body.onpointerdown=function(e){console.log('pointerdown');isDrawing=true;points.push({x:e.clientX,y:e.clientY});};document.body.onpointermove=function(e){console.log('pointermove');if(isDrawing){draw(e.clientX,e.clientY);}};document.body.onpointerup=function(e){if(isDrawing){draw(e.clientX,e.clientY);}points=[];isDrawing=false;};functiondraw(mousex,mousey){points.push({x:mousex,y:mousey});ctx.beginPath();letx=(points[points.length-2].x+points[points.length-1].x)/2,y=(points[points.length-2].y+points[points.length-1].y)/2;if(points.length==2){ctx.moveTo(points[points.length-2].x,points[points.length-2].y);ctx.lineTo(x,y);}else{letlastX=(points[points.length-3].x+points[points.length-2].x)/2,lastY=(points[points.length-3].y+points[points.length-2].y)/2;ctx.moveTo(lastX,lastY);ctx.quadraticCurveTo(points[points.length-2].x,points[points.length-2].y,x,y);}ctx.stroke();points.slice(0,1);}</script></body></html>

感谢你能够认真阅读完这篇文章,希望小编分享的“在html5中怎么使用canvas画板实现平滑曲线”这篇文章对大家有帮助,同时也希望大家多多支持亿速云,关注亿速云行业资讯频道,更多相关知识等着你来学习!