最終實(shí)現(xiàn)效果
實(shí)現(xiàn)思路:
獲取到canvas繪制后屏幕上像素點(diǎn)的數(shù)組渗钉,在目標(biāo)像素點(diǎn)上繪制粒子替換掉原來的內(nèi)容
- 繪制文字
- 通過API獲取畫布的二進(jìn)制數(shù)組
- 設(shè)置粒子的填充步長
- 添加粒子
- 循環(huán)的遍歷粒子,更新粒子的狀態(tài)
代碼實(shí)現(xiàn)
繪制文字
context.textAlign = "center";
context.font = this.size + "px arial";
context.fillText(this.text, this.x, this.y);
獲取二進(jìn)制
數(shù)組
let idata = context.getImageData(0, 0, canvas.width, canvas.height); // 獲取 canvas指定范圍內(nèi)的 像素?cái)?shù)組
let buffer32 = new Uint32Array(idata.data.buffer); // 轉(zhuǎn)成32位的數(shù)組
這里使用的
getImageData()
方法是獲取畫布內(nèi)所有的像素點(diǎn)的二進(jìn)制
表示冗酿,在JS中使用Uint32Array
來接收丸卷,已數(shù)組形式展現(xiàn),沒有渲染的地方數(shù)組值是0弟翘,有渲染的地方為一個(gè)非0的數(shù)字
填充粒子
// 遍歷所有的數(shù)組
for (var j = 0; j < canvas.height; j += gridY) {//步長
for (var i = 0; i < canvas.width; i += gridX) {//步長
if (buffer32[j * canvas.width + i]) {
// 放入粒子對象
var ball = new Particle(i, j);
this.placement.push(ball);
}
}
}
這里的意思是在二進(jìn)制數(shù)組中某一個(gè)范圍內(nèi)的粒子的密度箩做,其中步長越小越密集
更新粒子狀態(tài)
(function drawFrame() {
window.requestAnimationFrame(drawFrame);
context.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < word.placement.length; i++) {
//調(diào)用particle對像的drawParticle方法莽红,開始畫布上畫
word.placement[i].drawParticle();
}
}())
this.drawParticle = function () {
// 當(dāng)前粒子變小到一定程度之后,每次將它的半徑+0.1邦邦,使其慢慢變大
if (this.radius < this.futurRadius && this.dying === false) {
this.radius += durVal;
} else { //粒子已經(jīng)到達(dá)最大狀態(tài)
this.dying = true; //表示粒子還處于show狀態(tài)
}
//每次-0.1
if (this.dying) {
this.radius -= durVal;
}
// 畫粒子形狀
context.save();
context.fillStyle = this.color;
context.beginPath();
context.fillRect(this.x, this.y, this.futurRadius, this.futurRadius)
context.closePath();
context.fill();
context.restore();
//將消失的粒子重置最初的狀態(tài)
if (this.y < 0 || this.radius < 1) {
this.x = this.base[0];
this.y = this.base[1];
this.dying = false;
this.futurRadius = randomInt(1.1, 5.1);
}
}
完整代碼
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<canvas id="dir" width="800" height="800" style="border:1px solid #ccc">
</canvas>
<script>
var canvas = document.getElementById("dir");
var context = canvas.getContext("2d");
var gridY = 10,
gridX = 10,
colors = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5',
'#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4CAF50',
'#8BC34A', '#CDDC39', '#FFEB3B', '#FFC107', '#FF9800',
'#FF5722'
],
durVal = 0.1;
// 粒子
function Particle(x, y) {
this.x = x;
this.y = y;
this.color = colors[Math.floor(Math.random() * colors.length)]; //'bleack'//
this.futurRadius = randomInt(1.1, 5.1);
this.radius = 1.1;
this.dying = false;
this.base = [x, y];
this.drawParticle = function () {
// 當(dāng)前粒子變小到一定程度之后安吁,每次將它的半徑+0.1,使其慢慢變大
if (this.radius < this.futurRadius && this.dying === false) {
this.radius += durVal;
} else { //粒子已經(jīng)到達(dá)最大狀態(tài)
this.dying = true; //表示粒子還處于show狀態(tài)
}
//每次-0.1
if (this.dying) {
this.radius -= durVal;
}
// 畫粒子形狀
context.save();
context.fillStyle = this.color;
context.beginPath();
context.fillRect(this.x, this.y, this.futurRadius, this.futurRadius)
context.closePath();
context.fill();
context.restore();
//將消失的粒子重置最初的狀態(tài)
if (this.y < 0 || this.radius < 1) {
this.x = this.base[0];
this.y = this.base[1];
this.dying = false;
this.futurRadius = randomInt(1.1, 5.1);
}
}
}
function Shape(x, y, texte) {
this.x = x;
this.y = y;
this.size = 200;
this.text = texte;
this.placement = [];
}
Shape.prototype.getValue = function () {
context.textAlign = "center";
context.font = this.size + "px arial";
context.fillText(this.text, this.x, this.y);
let idata = context.getImageData(0, 0, canvas.width, canvas.height); // 獲取 canvas指定范圍內(nèi)的 像素?cái)?shù)組
let buffer32 = new Uint32Array(idata.data.buffer); // 轉(zhuǎn)成32位的數(shù)組
// 遍歷所有的數(shù)組
for (var j = 0; j < canvas.height; j += gridY) {
for (var i = 0; i < canvas.width; i += gridX) {
if (buffer32[j * canvas.width + i]) {
// 放入粒子對象
var ball = new Particle(i, j);
this.placement.push(ball);
}
}
}
context.clearRect(0, 0, canvas.width, canvas.height);
}
function randomInt(min, max) {
return min + Math.random() * (max - min + 1);
}
var word = new Shape(canvas.width / 2, canvas.height / 2, '文字粒子')
word.getValue
(function drawFrame() {
window.requestAnimationFrame(drawFrame);
context.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < word.placement.length; i++) {
//調(diào)用particle對像的drawParticle方法燃辖,開始畫布上畫
word.placement[i].drawParticle();
}
}())
</script>
</body>
</html>