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 = https://www.cnblogs.com/cs-whut/p/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 id="myCanvas1" style="position: absolute; " hidden></canvas>
<canvas id="myCanvas2" style="position: absolute;"></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 = https://www.cnblogs.com/cs-whut/p/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所示的粒子文本,

圖1 skip=1時顯示的粒子文本
由圖1可以看出拼湊文本的粒子非常密集,這是因為程式中遍歷的步長skip=1,這樣掃描了canvas1指定區域內的所有像素點,實際上在形成粒子文本時,無需所有像素點一個像素一個像素地掃,可以增大skip值,使得最后產生的粒子稀疏些,
例如,將程式中的陳述句“skip=1”修改為“skip=4”,則在瀏覽器視窗中繪制出如圖2所示的粒子文本,

圖2 skip=4時顯示的粒子文本
2.粒子文本的動態效果
了解了普通粒子文本的實作原理后,可以為拼湊文本的粒子添加一些動態動效,從2個方面著手,
(1)給粒子賦予一些隨機的位移,避免看上去過于整齊,
(2)粒子的大小隨機產生,在創建粒子時對粒子初始半徑radius 進行random 取隨機值,另外為了讓粒子半徑動態改變,增加一個屬性dynamicRadius,代表粒子的渲染半徑,它根據粒子的初始半徑radius,采用三角函式進行平滑改變,
撰寫如下的HTML代碼,
<html>
<head>
<title>粒子文本的動態效果</title>
</head>
<body>
<canvas id="myCanvas1" style="position: absolute; " hidden></canvas>
<canvas id="myCanvas2" style="position: absolute;"></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 = https://www.cnblogs.com/cs-whut/p/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所示的粒子文本動態效果,

圖3 粒子文本的動態效果
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/34153.html
標籤:JavaScript
