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小游戏实现代码
Aug 19 Javascript
js使用栈来实现10进制转8进制与取除数及余数
Jun 11 Javascript
JS+DIV+CSS实现的经典标签切换效果代码
Sep 14 Javascript
谈谈JavaScript自定义回调函数
Oct 18 Javascript
jQuery实现模拟flash头像裁切上传功能示例
Dec 11 Javascript
Angular 4依赖注入学习教程之FactoryProvider配置依赖对象(五)
Jun 04 Javascript
详解windows下vue-cli及webpack 构建网站(三)使用组件
Jun 17 Javascript
JS继承与闭包及JS实现继承的三种方式
Oct 15 Javascript
在vue中使用jointjs的方法
Mar 24 Javascript
koa2+vue实现登陆及登录状态判断
Aug 15 Javascript
JS localStorage存储对象,sessionStorage存储数组对象操作示例
Feb 15 Javascript
vue实现简单数据双向绑定
Apr 28 Vue.js
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
使用Apache的rewrite技术
2006/06/22 PHP
用PHP和ACCESS写聊天室(八)
2006/10/09 PHP
让的PHP代码飞起来的40条小技巧(提升php效率)
2010/04/12 PHP
php5.5中类级别的常量使用介绍
2013/10/02 PHP
PHP伪造来源HTTP_REFERER的方法实例详解
2015/07/06 PHP
php用xpath解析html的代码实例讲解
2019/02/14 PHP
微信推送功能实现方式图文详解
2019/07/12 PHP
PHP如何开启Opcache功能提升程序处理效率
2020/04/27 PHP
javascript 强制刷新页面的实现代码
2009/12/13 Javascript
xheditor与validate插件冲突的解决方案
2010/04/15 Javascript
javascript (用setTimeout而非setInterval)
2011/12/28 Javascript
在jQuery ajax中按钮button和submit的区别分析
2012/10/07 Javascript
使用JavaScript实现ajax的实例代码
2016/05/11 Javascript
基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解
2016/07/18 Javascript
vue父子组件的数据传递示例
2017/03/07 Javascript
node使用UEditor富文本编辑器的方法实例
2017/07/11 Javascript
Vue实现数字输入框中分割手机号码的示例
2017/10/10 Javascript
nodejs连接mysql数据库及基本知识点详解
2018/03/20 NodeJs
react-native动态切换tab组件的方法
2018/07/07 Javascript
微信小程序实现tab左右切换效果
2020/11/15 Javascript
微信小程序 调用远程接口 给全局数组赋值代码实例
2019/08/13 Javascript
layui的layedit富文本赋值方法
2019/09/18 Javascript
Vue快速实现通用表单验证的方法
2020/02/24 Javascript
jQuery zTree如何改变指定节点文本样式
2020/10/16 jQuery
JS实现百度搜索框
2021/02/25 Javascript
[04:04]显微镜下的DOTA2第六期——电影级别的华丽团战
2014/06/20 DOTA
深入理解Javascript中的this关键字
2015/03/27 Python
pycharm运行出现ImportError:No module named的解决方法
2018/10/13 Python
python利用requests库模拟post请求时json的使用教程
2018/12/07 Python
使用Python自动化破解自定义字体混淆信息的方法实例
2019/02/13 Python
Python 用turtle实现用正方形画圆的例子
2019/11/21 Python
python求一个字符串的所有排列的实现方法
2020/02/04 Python
开工仪式主持词
2014/03/20 职场文书
审计专业自荐信范文
2014/04/21 职场文书
群众路线问题查摆对照检查材料
2014/10/04 职场文书
光荣之路观后感
2015/06/12 职场文书