canvas是使用JavaScript程序绘图(动态生成),相比于css,可以更加简单方便的绘制细节的样式。其中最强大的功能莫过去像素的处理。一个像素一个像素去绘制任何想要的展示效果。接下来,要为各位观众姥爷去介绍一下文字动态粒子效果,当然是一些比较简单。如果各位观众姥爷感兴趣,可以在此基础上扩展。
相关实例源码下载:
HTML5 Canvas发光粒子文字动画特效
HTML5 Canvas液态粒子汇聚文字动画特效源码
HTML5 Canvas英文字母变化粒子动画特效
1.了解一下基本的canvas的Api,像画点,画圆,以及填充颜色等等。2.文字打碎,记录每个文字所在画布中的位置,本文的重点。3.生成随机粒子,并且设置每个粒子的运动轨迹。4.移动到步骤二记录下来位置。5.使用requestAnimationFrame来绘制每一帧的画布
就这么简单,只要100行代码,就能学会简单的文字动态效果
了解基本的canvas API,怎么这么懒!!!!还要我给找地址。戳这里)
获取文字位置信息,还不想让用户看到,这就需要用到两个画布了,下面是创建主画布,设置画布的大小。
let WIDTH,HEIGHT,cxt,raf,points;
window.onload = () => {
WIDTH = document.body.clientWidth;
HEIGHT = document.body.clientHeight;
const canvas = document.getElementById('canvas'); //主画布
canvas.width = WIDTH;
canvas.height = HEIGHT;
ctx = canvas.getContext('2d');
points = createViceCanvas(); // 创建副画布,写出想展示的文字,并且获取文字的位置信息。
init()
}
创建一个副画布,里面写入想要展示的文字,获取到文字粒子的位置。这里要注意了,主画布和副画布大小要一样,这样副画布里面的点位,才能正确的在主画布中展示。副画布创建好后,无需添加到dom中。这里写入了文字 www,
function createViceCanvas() {
const viceCanvas = document.createElement('canvas')
viceCanvas.width = WIDTH;
viceCanvas.height = HEIGHT;
let viceCxt = viceCanvas.getContext('2d')
initCanvas(viceCxt)
return getFontInfo(viceCxt); // 获取文字粒子的位置信息
}
function initCanvas(ctx){ //ctx 是副画布
const font = 'www'
ctx.font = '200px Arial';
const measure = ctx.measureText(font)
ctx.fillText(font, (WIDTH - measure.width) / 2, HEIGHT / 2);
}
这里使用了方法measureText,获取文字的宽度,为了能够在画布中间绘制文字。高度居中,感兴趣的可以自行尝试。。
如何获取文字的位置?上课了,划重点。
function getFontInfo(ctx) { //ctx是副画布,文字取点,获取每个文字在画布中的坐标。
let imageData = ctx.getImageData(0,0,WIDTH,HEIGHT).data;
const particles = [];
for(let x = 0; x < WIDTH; x += 4) {
for(let y=0; y < HEIGHT; y += 4) {
const fontIndex = (x + y * WIDTH) * 4 + 3;
if(imageData[fontIndex] > 0) {
particles.push(new Particle({
x,
y,
}))
}
}
}
return particles;
}
data属性返回一个 Uint8ClampedArray,它可以被使用作为查看初始像素数据。每个像素用4个1bytes值(按照红,绿,蓝和透明值的顺序; 这就是"RGBA"格式) 来代表。每个颜色值部份用0至255来代表。每个部份被分配到一个在数组内连续的索引,左上角像素的红色部份在数组的索引0位置。像素从左到右被处理,然后往下,遍历整个数组
我这里使用的画布大小是 1080 * 768, 用坐标系来表示就是x轴1080,y轴768
其实就是RGBA(255,255,255,0) 这四个类似的数字表示一个像素,那1080*768这个画布用Uint8ClampedArray数组表示,总共由多少个元素呢?就是1080 * 768 * 4 个元素
下面画了一张简陋的坐标图。
比如x轴(1,1)这个位置,需要用Uint8ClampedArray数组的前四位表示.
x轴(2,1)这个位置,需要用Uint8ClampedArray索引4-7的元素表示。
那坐标(1,2)第一位对应表示Uint8ClampedArray索引就是(1080*(2-1) + (1-1)) * 4 -1 .
坐标(m,n)首位索引对应的就是(width*(n-1) + m-1)) * 4 -1。 不懂的观众姥爷可以慢慢品一下。~~~~~
这里还有一个小技巧,rgba表示的颜色,第四个元素表示透明度,当我们画布上并未绘制内容时,第四个元素位0。所以,源码中const
fontIndex = (x + y * WIDTH) * 4 + 3
取到透明度不为0时候,则证明当前像素是有内容的,即可获取到文字在画布中的位置。
上面一步获取了文字粒子在画布中的位置,我们想要的效果,是粒子动画, 则我们需要在随机生成一个粒子, 然后移动到对应的获取到的文字位置。
class Particle {
constructor(center) {
this.x = center.x; // 记录点位最终应该停留在的x轴位置
this.y = center.y; // 记录点位最终应该停留在的y轴位置
this.item = 0; // 贝塞尔曲线系数
this.vx = 20; // 点位在x轴的移动速度
this.vy = 16; // 点位在y轴的移动速度
this.initX = Math.random() * WIDTH; // 点位随机在画布中的x坐标
this.initY = Math.random() * HEIGHT; // 点位随机在画布中的y坐标
}
draw(){ // 绘制点位
ctx.beginPath();
const {x, y} = threeBezier( // 贝塞尔曲线,获取每一个tick点位所在位置
this.item,
[this.initX,this.initY],
[this.x,this.y],
[this.x,this.y],
[this.x, this.y]
)
ctx.arc(x, y, 2, 0, 2 * Math.PI, true);
ctx.fillStyle="red"
ctx.fill();
ctx.closePath();
this.speed(); // 点位下次tick绘制时的坐标
}
speed() { // 每个点位绘制后的坐标
this.initX +=this.vx;
this.initY +=this.vy;
this.item += 0.005;
}
}
这里,需要一个随机粒子, 用来做移动,并且最后要组成一个文字,文字的最终位置我们已经获取到了,就是constructor的参数center。那粒子该怎么运动呢?我这里使用的贝塞尔曲线,并且封装成了一个方法。
本文系作者在时代Java发表,未经许可,不得转载。
如有侵权,请联系nowjava@qq.com删除。