【canvas】文字粒子效果

这个效果当初看到时完全是惊呆了,觉得好炫啊,觉得前端好好玩。今天得空,实现了一个。效果还不错,准备将其改进,并运用到博客头图中,想想就有点小激动。

 一、原理分析

这个效果可以分成两个部分,第一部分是讲文字粒子化,第二部分是设置各个粒子的运动轨迹。

第一部分的实现需要借助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