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 相关文章推荐
jquery 锁定弹出层实现代码
Feb 23 Javascript
Jquery.TreeView结合ASP.Net和数据库生成菜单导航条
Aug 27 Javascript
juqery 学习之三 选择器 简单 内容
Nov 25 Javascript
jQuery的层级查找方式分析
Jun 16 Javascript
JavaScript职责链模式概述
Sep 17 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
Sep 26 Javascript
如何解决vue与传统jquery插件冲突
Mar 20 Javascript
微信小程序中使用javascript 回调函数
May 11 Javascript
Angular4的输入属性与输出属性实例详解
Nov 29 Javascript
旺旺在线客服代码 旺旺客服代码生成器
Jan 09 Javascript
使用百度地图实现地图网格的示例
Feb 06 Javascript
Javascript设计模式之原型模式详细
Oct 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
php 上传文件类型判断函数(避免上传漏洞 )
2010/06/08 PHP
PHP5下$_SERVER变量不再受magic_quotes_gpc保护的弥补方法
2012/10/31 PHP
php简单实现快速排序的方法
2015/04/04 PHP
Discuz论坛密码与密保加密规则
2016/12/19 PHP
PHP-FPM的配置与优化讲解
2019/03/15 PHP
php redis setnx分布式锁简单原理解析
2020/10/23 PHP
浅析jQuery中常用的元素查找方法总结
2013/07/04 Javascript
jquery.ui.draggable中文文档(原文翻译)
2013/11/15 Javascript
用jquery中插件dialog实现弹框效果实例代码
2013/11/15 Javascript
js修改原型的属性使用介绍
2014/01/26 Javascript
Javascript限制网页只能在微信内置浏览器中访问
2014/11/09 Javascript
jQuery实现鼠标划过添加和删除class的方法
2015/06/26 Javascript
jquery获得当前html页面源码的方法
2015/07/14 Javascript
jQuery+css实现的蓝色水平二级导航菜单效果代码
2015/09/11 Javascript
基于vue+canvas的excel-like组件实例详解
2017/11/28 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
JavaScript原型对象、构造函数和实例对象功能与用法详解
2018/08/04 Javascript
JavaScript前端开发时数值运算的小技巧
2020/07/28 Javascript
Python实现读取目录所有文件的文件名并保存到txt文件代码
2014/11/22 Python
python实现搜索指定目录下文件及文件内搜索指定关键词的方法
2015/06/28 Python
python批量提取word内信息
2015/08/09 Python
对pandas将dataframe中某列按照条件赋值的实例讲解
2018/11/29 Python
opencv导入头文件时报错#include的解决方法
2019/07/31 Python
浅谈PyQt5中异步刷新UI和Python多线程总结
2019/12/13 Python
Python调用scp向服务器上传文件示例
2019/12/22 Python
Python的pygame安装教程详解
2020/02/10 Python
深入理解Tensorflow中的masking和padding
2020/02/24 Python
python使用paramiko实现ssh的功能详解
2020/03/06 Python
localstorage和sessionstorage使用记录(推荐)
2017/05/23 HTML / CSS
养殖项目策划书范文
2014/01/13 职场文书
巡警年度自我鉴定
2014/02/21 职场文书
高中生职业生涯规划书
2014/02/24 职场文书
双方协议书
2014/04/22 职场文书
2014领导班子四风剖析对照检查材料思想汇报
2014/09/20 职场文书
2016年少先队活动总结
2016/04/06 职场文书
CSS filter 有什么神奇用途
2021/05/25 HTML / CSS