JavaScript動畫實例:粒子文本

1.粒子文本的實現原理

      粒子文本的實現原理是:使用兩張 canvas,一張是用戶看不到的canvas1,用來繪製文本;另外一張是用戶看到的canvas2,用來根據canvas1中繪製的文本數據來生成粒子。html

     先在canvas1中用以下的語句繪製待顯示的文本。編程

    ctx1.font = '100px PingFang SC';canvas

    ctx1.textAlign = 'center';數組

    ctx1.baseline = 'middle';瀏覽器

    ctx1.fillText('Happy New Year',canvas1.width/2, canvas1.height/2);app

      而後使用canvas API的getImageData方法,獲取一個ImageData對象,這個對象用來描述 canvas 指定區域內的像素數據。語句爲:dom

       var imgData = ctx1.getImageData(0, 0, canvas1.width, canvas1.height).data;函數

      這樣imgData中保存了canvas1指定區域內全部像素點的rgba值,它是一個數組。因爲每一個像素點有 rgba 四個值,因此這個數組的長度也就是「像素點數量 * 4」。oop

      最後經過遍歷imgData數組,能夠判斷在canvas1中,哪些點是有色彩的(處於文本中間),哪些點是沒有色彩的(不在文本上),把那些有色彩的像素位置記下來,而後在用戶可見canvas2上生成粒子並繪製粒子便可。具體編程遍歷imgData數組時,能夠根據透明度,也就是 rgba 中的第4個元素是否不爲0來判斷該像素是否在文本中。this

      爲此,建立一個自定義的粒子類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 = 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 = 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  粒子文本的動態效果 

相關文章
相關標籤/搜索