本篇文章给大家分享的是有关使用帆布怎么实现一个像素画板,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
Pixel =, function (选项),{ ,,,this.x =, option.x; ,,,this.y =, option.y; ,,,this.shape =, option.shape; ,,,this.size =, option.size | |, 8; }
x和y表示中心点坐标,一开始我是这么做的,先定义路径
createPath:, function (ctx), { if (this.shape ===, & # 39;圆# 39;),{ this.createCircle (ctx); },else if (this.shape ===, & # 39;矩形# 39;),{ this.createRect (ctx); },{else this.createCircle (ctx); } }, createCircle: function (ctx), { var radius =, this.size /, 2; ctx.arc (this.x this.y,半径,0,Math.PI * 2); }, createRect: function (ctx), { var points =, this.getPoints (); ,,,,,,,,,,,points.forEach (function (我)点,,,{ ,,,,,,,,,,,,,,,ctx[小姐:==,0,?,& # 39;移至# 39;,:,& # 39;画线# 39;](point.y point.x也); ,,,,,,,,,,,}) ,,,,,,,,,,,ctx.lineTo(点[0]。x,,点[0].y); },
像素网格支持圆形和矩形,路径定义好后,然后进行绘制
:画,function (ctx), { ctx.save (); ctx.lineWidth=this.lineWidth; ctx.strokeStyle=this.strokeStyle; ctx.fillStyle=this.fillStyle; ctx.beginPath (); this.createPath (ctx); ctx.stroke (); 如果(this.isFill) {ctx.fill ();} ctx.restore (); }
然后通过循环批量创建像素网格:
for (var 小姐:=,stepX +, 5,,小姐:& lt;, canvas.width;,我+=stepX), { 时间=for (var j stepY +, 5;, j & lt;, canvas.height;, j +=stepY), { var pixel =, new 像素({ x:,我, y: j, 形状:& # 39;圆# 39; }) box.push(像素); pixel.draw (ctx); } }
这样做看似完美,然而有一个巨大毙命,每画一个像素都回绘制到上下文中,每一次都在改变画布的状态,这样做会导致渲染性能太差,因为像素点很多,如果画布比较大,性能很是令人堪忧,并且画板上面还有一些操作,如此频繁改变画布的状态是不合适的。
因此,正确的做法是:我们应该定义好所有的路径,最好在一次性的批量绘制到画布中,,
//定义像素的位置 for (var 小姐:=,stepX +, 5,,小姐:& lt;, canvas.width;,我+=stepX), { 时间=for (var j stepY +, 5;, j & lt;, canvas.height;, j +=stepY), { var pixel =, new 像素({ x:,我, y: j, 形状:& # 39;圆# 39; }) box.push(像素); } }//批量绘制 console.time(& # 39;时间# 39;); ctx.beginPath (); 时间=for (var c 0;, c & lt;, box.length;, c++), { var circle =,盒子[c]; ctx.moveTo (circle.x +, 3, circle.y); circle.createPath (ctx); } ctx.closePath (); ctx.stroke (); console.timeEnd(& # 39;时间# 39;);
可以看到这个渲染效率很快,尽可能少的改变画布的状态,因为每改变一次上下文的状态,画布都会重新绘制,这种状态是全局的状态。
<强>像素网格交互强>
项目的需求,是在画布上鼠标按下移动,可以擦除像素点,这里面包含两个知识点,一个是如何获取鼠标移动路径上的像素网格,二是性能问题,因为我们这个需求的要求是绘制八万个点,不说别的,光是循环都得几十上百毫秒,何况还要绘制渲染。我们先来看第一个问题:
<强>获取鼠标移动路径下的网格强>
看到这个问题,我们很容易想到,写个函数,通过鼠标的位置获取下所在的位置包含那个网格,然后每次移动都重新更新位置计算,这样看是可以完成需求,但是如果鼠标移动过的快,是无法做的到,每个点的位置都可以计算到的,效果会不连贯。我们换种思路,鼠标经过的路径,我们可以很明确的知道起始和终点,我们把整个绘制路径想象成一段段的线段,那么问题就变成,线段与原相交的一个算法了,线段就是画笔的粗,细线段经过的路径就是鼠标运动的路径,与之相交的圆就是需要变化样式的网格。转换成代码就是如下: