使用帆布怎么实现一个像素画板

  介绍

本篇文章给大家分享的是有关使用帆布怎么实现一个像素画板,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

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;);

使用帆布怎么实现一个像素画板

可以看到这个渲染效率很快,尽可能少的改变画布的状态,因为每改变一次上下文的状态,画布都会重新绘制,这种状态是全局的状态。

<强>像素网格交互

项目的需求,是在画布上鼠标按下移动,可以擦除像素点,这里面包含两个知识点,一个是如何获取鼠标移动路径上的像素网格,二是性能问题,因为我们这个需求的要求是绘制八万个点,不说别的,光是循环都得几十上百毫秒,何况还要绘制渲染。我们先来看第一个问题:

<强>获取鼠标移动路径下的网格

看到这个问题,我们很容易想到,写个函数,通过鼠标的位置获取下所在的位置包含那个网格,然后每次移动都重新更新位置计算,这样看是可以完成需求,但是如果鼠标移动过的快,是无法做的到,每个点的位置都可以计算到的,效果会不连贯。我们换种思路,鼠标经过的路径,我们可以很明确的知道起始和终点,我们把整个绘制路径想象成一段段的线段,那么问题就变成,线段与原相交的一个算法了,线段就是画笔的粗,细线段经过的路径就是鼠标运动的路径,与之相交的圆就是需要变化样式的网格。转换成代码就是如下:

使用帆布怎么实现一个像素画板