canvas粒子动画教程,canvas粒子动态效果
本文介绍了画布文字转粒子效果的实现代码,分享给大家,希望对你有所帮助,如下:
用粒子画文字让人觉得很有意思,随着粒子的移动效果会更加酷炫。介绍了在画布上用粒子绘制文本的方法。
实现原理
总的来说,把文字变成粒子显示的效果,其实很简单。实现的原理是用两块画布,一块是用户看不见的画布,用来画文字;另一个是用户看到的B canvas,用来根据a的文本数据生成粒子,直观表示如图:
创建离屏 canvas
HTML只需要放置主画布:
!- HTML结构-htmlhead./head body canvas id= stage /canvas/body/html然后创建一个屏幕外画布并绘制文本:
const WIDTH=window.innerWidthconst HEIGHT=window . inner HEIGHT;const offscreen canvas=document . createelement( canvas );const offscreenCtx=offscreencanvas . get context( 2d );offscreenCanvas.width=WIDTHoffscreenCanvas.height=HEIGHToffscreenCtx.font=100px方平SC ;offscreenctx . textalign= center ;offscreenctx . baseline= middle ;offscreenCtx.fillText(Hello ,WIDTH/2,HEIGHT/2);此时页面上什么也没有发生,但实际上可以在屏幕外的画布上想象出来。此时,应该如图所示:
核心方法 getImageData
使用canvas的getImageData方法获取ImageData对象,用于描述canvas指定区域的像素数据。也就是说,我们可以得到文本“Hello”的每个像素的位置和颜色,然后在指定的位置生成粒子。最后的结果是粒子拼凑成文字。
要获取像素信息,需要使用ImageData对象的data属性,它将所有像素的rgba值展开成一个数组,每个像素有四个rgba值,这个数组的个数就是像素数* 4。
假设我选择了一个3 * 4的区域,那么总共有12个像素,每个像素有4个rgba的值,那么数据的数组就有12 * 4=48个元素。
如果打印出数据,可以看到rgba从左到右、从上到下排列这些像素。
当然,我们想要得到的区域必须包含文本,所以我们应该得到整个屏幕外的画布区域:
const img data=offscreenctx . getimagedata(0,0,WIDTH,HEIGHT)。数据;生成粒子
得到ImageData后,通过遍历数据数组,可以判断出离屏画布的画布中哪些点是着色的(在文本中间),哪些点是不着色的(不在文本中)。记下这些彩色像素的位置,然后在主画布上生成粒子。没关系。
首先,创建一个粒子类:
class Particle { constructor(options={ }){ const { x=0,y=0,color=#fff ,radius=5 }=optionsthis.radius=radiusthis.x=xthis.y=ythis.color=color} draw(CTX){ CTX . begin path();ctx.arc(this.x,this.y,this.radius,0,2 * Math。圆周率,假);CTX . fill style=this . color;CTX . fill();CTX . close path();}}遍历数据,我们可以根据透明度判断像素是否在文本中,即rgba中的第四个元素是否不为0。
常量粒子=[];const skip=4;for(var y=0;y高度;y=skip){ for(var x=0;x宽度;x=skip){ var opacity index=(x y * WIDTH)* 4 3;if(img data[opacity index]0){ particles . push(new Particle({ x,y,radius: 1,color: # 2 ea 9 df });}}}我们使用粒子数组来存储所有的粒子。这里skip的作用是遍历的步长。如果我们一个像素一个像素地扫描,最后拼凑出文字的粒子会非常密集。增加该值,产生的粒子将更加稀疏。
最后,创建主画布并绘制它:
const canvas=document . query selector(# stage));canvas.width=宽度;canvas.height=高度;const CTX=canvas . get context( 2d );for(粒子的常数粒子){ particle . draw(CTX);}效果如下:
完整代码见01-基本-文本-粒子。
添加效果
了解了实现的原理之后,其实其他的一切都是给粒子添加一些动态效果。首先,粒子可以有一些随机的位移,以避免看起来太整齐。
常量粒子=[];const skip=4;for(var y=0;y高度;y=skip){ for(var x=0;x宽度;x=skip){ var opacity index=(x y * WIDTH)* 4 3;If (imgData[opacityIndex] 0) {//添加随机位移粒子. push(new particle({ x:xmath . random()* 6-3,y: ymath.random () * 6-3,radius: 1,color: # 2ea9df) }}}效果如下:
如果想达到更大的效果,比如:
如何实现这一点?首先我们需要随机生成粒子大小,在创建粒子时只需要随机生成半径。此外,如果希望粒子半径动态变化,需要区分粒子的渲染半径和初始半径,使用requestAnimationFrame进行动画渲染:
class Particle { constructor(options={ }){ const { x=0,y=0,color=#fff ,radius=5 }=optionsthis.radius=radius//.this.dynamicRadius=radius//添加dynamicRadius属性} draw (CTX) {//.ctx.arc (this.x,this.y,this.dynamic radius,0,2 * math.pi,false);//替换为动态半径//.} update(){//todo } } request animation帧(函数loop () {requestanimation帧(loop));ctx.fillStyle= # fffctx.fillRect(0,0,宽度,高度);for(粒子的常数粒子){ particle . update();particle . draw(CTX);}});那么关键就在于如何实现粒子的更新方法。假设我们希望粒子半径从1到5平滑循环变化,很容易想到三角函数,比如:
横轴应该是时间相关的。您可以维护另一个变量,并在每次调用update时添加它。简单做一下,也可以直接用时间戳计算。更新方法的示例如下:
update(){ this . dynamic radius=3 ^ 2 * math . sin(new Date()/1000% 1000 * this . radius);}完整代码请参见02-文本到粒子-尺寸变化。
这就是本文的全部内容。希望对大家的学习和支持有帮助。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。