JavaScript动画实例之粒子文本的实现方法详解


Posted in Javascript onJuly 28, 2020

1.粒子文本的实现原理

粒子文本的实现原理是:使用两张 canvas,一张是用户看不到的canvas1,用来绘制文本;另一张是用户看到的canvas2,用来根据canvas1中绘制的文本数据来生成粒子。

先在canvas1中用如下的语句绘制待显示的文本。

ctx1.font = '100px PingFang SC';

ctx1.textAlign = 'center';

ctx1.baseline = 'middle';

ctx1.fillText('Happy New Year',canvas1.width/2, canvas1.height/2);

然后使用canvas API的getImageData方法,获取一个ImageData对象,这个对象用来描述 canvas 指定区域内的像素数据。语句为:var imgData = ctx1.getImageData(0, 0, canvas1.width, canvas1.height).data;

这样imgData中保存了canvas1指定区域内所有像素点的rgba值,它是一个数组。由于每个像素点有 rgba 四个值,所以这个数组的长度也就是“像素点数量 * 4”。

最后通过遍历imgData数组,可以判断在canvas1中,哪些点是有色彩的(处于文本中间),哪些点是没有色彩的(不在文本上),把那些有色彩的像素位置记下来,然后在用户可见canvas2上生成粒子并绘制粒子即可。具体编程遍历imgData数组时,可以根据透明度,也就是 rgba 中的第4个元素是否不为0来判断该像素是否在文本中。

为此,创建一个自定义的粒子类Particle,该类中每个粒子对象有坐标位置(x,y)、半径radius和颜色color等4个属性;有一个方法draw(),用于绘制粒子。

编写的HTML代码如下。

<html>

<head>

<title>普通粒子文本</title>

</head>

<body>

<canvas hidden></canvas>

<canvas></canvas>

<script>

var canvas1=document.getElementById('myCanvas1');

ctx1= canvas1.getContext('2d');

var canvas2=document.getElementById('myCanvas2');

ctx2= canvas2.getContext('2d');

canvas1.width = canvas2.width = window.innerWidth;

canvas1.height = canvas2.height = window.innerHeight;

ctx1.font = '100px PingFang SC';

ctx1.textAlign = 'center';

ctx1.baseline = 'middle';

ctx1.fillText('Happy New Year',canvas1.width/2, canvas1.height/2);

var imgData = ctx1.getImageData(0, 0, canvas1.width, canvas1.height).data;

function Particle(x,y,radius,color)

{

this.x = x;

this.y = y;

this.radius = radius;

this.color = color;

}

Particle.prototype.draw= function()

{

ctx2.beginPath();

ctx2.arc(this.x, this.y, this.radius, 0, 2 * Math.PI, false);

ctx2.fillStyle = this.color;

ctx2.fill();

ctx2.closePath();

}

var particles = [];

var skip =1;

for (var y = 0; y < canvas1.height; y +=skip)

{

for (var x = 0; x < canvas1.width; x += skip)

{

var opacityIndex = (x + y * canvas1.width) * 4 + 3;

if (imgData[opacityIndex] > 0)

{

var hue = Math.floor(Math.random() * 360);

var color=`hsl(${hue}, 100%, 50%)`;

particles.push(new Particle(x,y,2,color));

}

}

}

for (var particle of particles)

{

particle.draw();

}

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中绘制出如图1所示的粒子文本。

JavaScript动画实例之粒子文本的实现方法详解

图1 skip=1时显示的粒子文本

由图1可以看出拼凑文本的粒子非常密集,这是因为程序中遍历的步长skip=1,这样扫描了canvas1指定区域内的所有像素点。实际上在形成粒子文本时,无需所有像素点一个像素一个像素地扫,可以增大skip值,使得最后产生的粒子稀疏些。

例如,将程序中的语句“skip=1”修改为“skip=4”,则在浏览器窗口中绘制出如图2所示的粒子文本。

JavaScript动画实例之粒子文本的实现方法详解

图2 skip=4时显示的粒子文本

2.粒子文本的动态效果

了解了普通粒子文本的实现原理后,可以为拼凑文本的粒子添加一些动态动效。从2个方面着手。

(1)给粒子赋予一些随机的位移,避免看上去过于整齐。

(2)粒子的大小随机产生,在创建粒子时对粒子初始半径radius 进行random 取随机值。另外为了让粒子半径动态改变,增加一个属性dynamicRadius,代表粒子的渲染半径,它根据粒子的初始半径radius,采用三角函数进行平滑改变。

编写如下的HTML代码。

<html>

<head>

<title>粒子文本的动态效果</title>

</head>

<body>

<canvas hidden></canvas>

<canvas></canvas>

<script>

var canvas1=document.getElementById('myCanvas1');

ctx1= canvas1.getContext('2d');

var canvas2=document.getElementById('myCanvas2');

ctx2= canvas2.getContext('2d');

canvas1.width = canvas2.width = window.innerWidth;

canvas1.height = canvas2.height = window.innerHeight;

ctx1.font = '120px PingFang SC';

ctx1.textAlign = 'center';

ctx1.baseline = 'middle';

ctx1.fillText('Happy New Year',canvas1.width/2, canvas1.height/2);

var imgData = ctx1.getImageData(0, 0, canvas1.width, canvas1.height).data;

function Particle(x,y,radius,color)

{

this.x = x;

this.y = y;

this.radius = radius;

this.color = color;

this.dynamicRadius = radius;

}

Particle.prototype.draw= function()

{

ctx2.beginPath();

ctx2.arc(this.x, this.y,this.dynamicRadius, 0, 2 * Math.PI, false);

ctx2.fillStyle = this.color;

ctx2.fill();

ctx2.closePath();

}

Particle.prototype.update= function()

{

this.dynamicRadius =3+2*Math.sin(new Date()/1000%1000*this.radius);

}

function random(min,max)

{

return Math.random() * ( max - min ) + min;

}

var particles = [];

var skip =4;

for (var y = 0; y < canvas1.height; y +=skip)

{

for (var x = 0; x < canvas1.width; x += skip)

{

var opacityIndex = (x + y * canvas1.width) * 4 + 3;

if (imgData[opacityIndex] > 0)

{

var hue = Math.floor(Math.random() * 360);

var color=`hsl(${hue}, 100%, 50%)`;

particles.push(new Particle(x+random(1,3),y+random(1,3),random(1,4),color));

}

}

}

for (var particle of particles)

{

particle.draw();

}

function loop()

{

requestAnimationFrame(loop);

ctx2.clearRect(0,0,canvas2.width,canvas2.height);

for (var particle of particles)

{

particle.update();

particle.draw();

}

}

loop();

</script>

</body>

</html>

在浏览器中打开包含这段HTML代码的html文件,可以看到在浏览器窗口中呈现出如图3所示的粒子文本动态效果。

JavaScript动画实例之粒子文本的实现方法详解

图3 粒子文本的动态效果

到此这篇关于JavaScript动画实例之粒子文本的实现方法详解的文章就介绍到这了,更多相关JavaScript动画实例之粒子文本内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
一些Javascript的IE和Firefox(火狐)兼容性的问题总结及常用例子
May 21 Javascript
用jquery实现的模拟QQ邮箱里的收件人选取及其他效果(一)
Jan 06 Javascript
js实现不提交表单获取单选按钮值的方法
Aug 21 Javascript
干货分享:让你分分钟学会javascript闭包
Dec 25 Javascript
详解基于javascript实现的苹果系统底部菜单
Dec 02 Javascript
微信小程序获取循环元素id以及wx.login登录操作
Aug 17 Javascript
JS实现身份证输入框的输入效果
Aug 21 Javascript
JS中this的指向以及call、apply的作用
May 06 Javascript
详解Vue-axios 设置请求头问题
Dec 06 Javascript
JavaScript代码模拟鼠标自动点击事件示例
Aug 07 Javascript
Vue+Element UI 树形控件整合下拉功能菜单(tree + dropdown +input)
Aug 28 Javascript
JS前端可视化canvas动画原理及其推导实现
Aug 05 Javascript
Vue $emit()不能触发父组件方法的原因及解决
Jul 28 #Javascript
vue 遮罩层阻止默认滚动事件操作
Jul 28 #Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
Jul 28 #Javascript
处理JavaScript值为undefined的7个小技巧
Jul 28 #Javascript
vue中touch和click共存的解决方式
Jul 28 #Javascript
JS实现audio音频剪裁剪切复制播放与上传(步骤详解)
Jul 28 #Javascript
JavaScript中window和document用法详解
Jul 28 #Javascript
You might like
DSP接收机前端设想
2021/03/02 无线电
php分页原理 分页代码 分页类制作教程
2016/09/23 PHP
PHP面向对象五大原则之接口隔离原则(ISP)详解
2018/04/04 PHP
Laravel框架集合用法实例浅析
2020/05/14 PHP
Javascript 获取字符串字节数的多种方法
2009/06/02 Javascript
javascript回车完美实现tab切换功能
2014/03/13 Javascript
jquery图片播放浏览插件prettyPhoto使用详解
2014/12/19 Javascript
深入分析原生JavaScript事件
2014/12/29 Javascript
html+js实现简单的计算器代码(加减乘除)
2016/07/12 Javascript
基于jQuery的AJAX和JSON实现纯html数据模板
2016/08/09 Javascript
微信小程序 点击控件后选中其它反选实例详解
2017/02/21 Javascript
nodejs实现简单的gulp打包
2017/12/21 NodeJs
Vue头像处理方案小结
2018/07/26 Javascript
Angular6 正则表达式允许输入部分中文字符
2018/09/10 Javascript
js中火星坐标、百度坐标、WGS84坐标转换实现方法示例
2020/03/02 Javascript
vue+springboot+element+vue-resource实现文件上传教程
2020/10/21 Javascript
vue keep-alive的简单总结
2021/01/25 Vue.js
使用Python中的线程进行网络编程的入门教程
2015/04/15 Python
深入解析Python中的WSGI接口
2015/05/11 Python
在Python的Flask框架中构建Web表单的教程
2016/06/04 Python
详解python 发送邮件实例代码
2016/12/22 Python
Python实现破解猜数游戏算法示例
2017/09/25 Python
对numpy和pandas中数组的合并和拆分详解
2018/04/11 Python
利用Python实现原创工具的Logo与Help
2018/12/03 Python
Python:二维列表下标互换方式(矩阵转置)
2019/12/02 Python
Python字典生成式、集合生成式、生成器用法实例分析
2020/01/07 Python
Python模拟FTP文件服务器的操作方法
2020/02/18 Python
windows支持哪个版本的python
2020/07/03 Python
css3实现针线缝合效果(图解步骤)
2013/02/04 HTML / CSS
高级技校毕业生自荐信
2013/11/18 职场文书
售后服务承诺书模板
2014/05/21 职场文书
2015安全保卫工作总结
2015/04/25 职场文书
2015年学校精神文明工作总结
2015/05/27 职场文书
小学班主任工作随笔
2015/08/15 职场文书
python 破解加密zip文件的密码
2021/04/22 Python
简单总结SpringMVC拦截器的使用方法
2021/06/28 Java/Android