zoukankan      html  css  js  c++  java
  • JavaScript动画实例:粒子文本

    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 = 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 = 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  粒子文本的动态效果 

  • 相关阅读:
    P1364 医院设置
    Can you solve this equation?
    HDU 3732 Ahui Writes Word
    2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest H. Delete Them
    2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest J. Bottles
    数据结构--KMP算法总结
    Power Strings(KMP)
    KMP (next数组的性质及证明)
    KMP模板
    poj 3461 Oulipo(KMP模板题)
  • 原文地址:https://www.cnblogs.com/cs-whut/p/13334882.html
Copyright © 2011-2022 走看看