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中利用数组实现的循环队列代码
Jan 24 Javascript
jQuery中绑定事件的命名空间详解
Apr 05 Javascript
JavaScript操纵窗口的方法小结
Jun 28 Javascript
JS判断客服QQ号在线还是离线状态的方法
Jan 13 Javascript
jQuery实现仿百度帖吧头部固定导航效果
Aug 07 Javascript
javascript匀速运动实现方法分析
Jan 08 Javascript
基于JavaScript实现瀑布流布局(二)
Jan 26 Javascript
关于微信上网页图片点击全屏放大效果
Dec 19 Javascript
jquery+css实现简单的图片轮播效果
Aug 07 jQuery
JS实现元素上下左右移动效果
Oct 18 Javascript
使用Vue.js和Flask来构建一个单页的App的示例
Mar 21 Javascript
Vue混入mixins滚动触底的方法
Nov 22 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
PHP使用Redis实现防止大并发下二次写入的方法
2017/10/09 PHP
Laravel事件监听器用法实例分析
2019/03/12 PHP
js之WEB开发调试利器:Firebug 下载
2007/01/13 Javascript
javascript(jquery)利用函数修改全局变量的代码
2009/11/02 Javascript
比较搞笑的js陷阱题
2010/02/07 Javascript
关于eval 与new Function 到底该选哪个?
2013/04/17 Javascript
Web跨浏览器进程通信(Web跨域)
2013/04/17 Javascript
同域jQuery(跨)iframe操作DOM(示例代码)
2013/12/13 Javascript
非jQuery实现照片散落桌子上,单击放大的LightBox效果
2014/11/28 Javascript
浅谈Javascript中匀速运动的停止条件
2014/12/19 Javascript
JavaScript中的DSL元编程介绍
2015/03/15 Javascript
JS实现可调整倒计时间代码分享
2015/08/18 Javascript
javascript实现任务栏消息提示的简单实例
2016/05/31 Javascript
JQuery组件基于Bootstrap的DropDownList(完整版)
2016/07/05 Javascript
jQuery+CSS实现简单切换菜单示例
2016/07/27 Javascript
vue2笔记 — vue-router路由懒加载的实现
2017/03/03 Javascript
vue.js实例todoList项目
2017/07/07 Javascript
详解如何将 Vue-cli 改造成支持多页面的 history 模式
2017/11/20 Javascript
layui树形菜单动态遍历的例子
2019/09/23 Javascript
JS对日期操作封装代码实例
2019/11/08 Javascript
vue + node如何通过一个Txt文件批量生成MP3并压缩成Zip
2020/06/02 Javascript
python 动态加载的实现方法
2017/12/22 Python
详解Python3.6的py文件打包生成exe
2018/07/13 Python
Django xadmin开启搜索功能的实现
2019/11/15 Python
Python协程 yield与协程greenlet简单用法示例
2019/11/22 Python
详解Selenium 元素定位和WebDriver常用方法
2020/12/04 Python
css3弹性盒模型(Flexbox)详细介绍
2014/10/08 HTML / CSS
优瑞自动咖啡机官网:Jura
2018/09/29 全球购物
what is the difference between ext2 and ext3
2015/08/25 面试题
幼儿园实习自我鉴定
2013/12/15 职场文书
25岁生日感言
2014/01/13 职场文书
洗发水广告词
2014/03/13 职场文书
财务总监岗位职责
2015/02/03 职场文书
老公出轨后的保证书
2015/05/08 职场文书
嵌入式Redis服务器在Spring Boot测试中的使用教程
2021/07/21 Redis
VS2019连接MySQL数据库的过程及常见问题总结
2021/11/27 MySQL