这个效果当初看到时完全是惊呆了,觉得好炫啊,觉得前端好好玩。今天得空,实现了一个。效果还不错,准备将其改进,并运用到博客头图中,想想就有点小激动。
一、原理分析
这个效果可以分成两个部分,第一部分是讲文字粒子化,第二部分是设置各个粒子的运动轨迹。
第一部分的实现需要借助canvas的一个属性"imageData",它会返回canvas上所有像素信息列表。
第二部分需要在每一个粒子中储存始终位置信息,然后根据运动过程改变位置信息。
二、代码实现
核心代码:
// 将文字序列化成小球
function setBalls() {
balls = [];
var text = document.querySelector("#text_input").value;
var imgData = serializationText(text, screenWidth, screenHeight);
// 设置扫描间隔
for (var i = 0; i < imgData.width; i += 8) {
for (var j = 0; j < imgData.height; j += 8) {
var pos = (imgData.width * j + i) * 4,
colorR = imgData.data[pos];
// 当像素是文字像素时
if (colorR > 240) {
var x = Math.random() * screenWidth;
var y = Math.random() * screenHeight;
var r = Math.pow(Math.random() / 0.5, 2) * 3;
var dx = i;
var dy = j;
var dr = 3;
balls.push(new BallObj(x, y, r, dx, dy, dr));
}
}
}
}
// 主函数
function main() {
// 清空画布
context.clearRect(0, 0, screenWidth, screenHeight);
// 画小球
context.fillStyle = "red";
for (var i = 0; i < balls.length; i++) {
var ball = balls[i];
context.beginPath();
if (isReverse) {
ball.x = ball.x + (ball.sx - ball.x) * 0.1;
ball.y = ball.y + (ball.sy - ball.y) * 0.1;
ball.r = ball.r + (ball.sr - ball.r) * 0.1;
if (Math.abs(ball.x - ball.sx) < 0.001) {
isEnd = true;
}
} else {
ball.x = ball.x + (ball.ex - ball.x) * 0.1;
ball.y = ball.y + (ball.ey - ball.y) * 0.1;
ball.r = ball.r + (ball.er - ball.r) * 0.1;
if (Math.abs(ball.x - ball.ex) < 0.001 && !isPause) {
isPause = true;
setTimeout(function () {
isReverse = true;
}, 1000)
}
}
context.arc(ball.x, ball.y, ball.r, 0, Math.PI * 2);
context.fill();
}
if (!isEnd) {
window.requestAnimationFrame(arguments.callee);
}
}
这里是一个完整的 DEMO。