zoukankan      html  css  js  c++  java
  • JavaScript动画实例:沿圆周运动的圆圈

    1.一个沿圆周运动的圆圈

          一个半径为size的圆圈以画布的中心(canvas.width/2,canvas.height/2)为起点,沿着一个圆周运动。编写如下的HTML代码。

    <!DOCTYPE html>
    <html>
    <head>
    <title>沿圆周运动的圆圈</title>
    </head>
    <body>
    <script>
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      document.body.appendChild(canvas);
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      ctx.beginPath();
      ctx.fillStyle = 'rgba(0, 0, 0, 1)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      var angle =360;
      var pos = [canvas.width/2,canvas.height/2];
      var size = 10;
      var speed = 1;
      var curve = 0.5;
      var color = 'rgba(69,204,255,.95)';
      function draw () 
      {
         var radians = angle*Math.PI/180;
         pos[0] += Math.cos(radians)* speed;
         pos[1] += Math.sin(radians)* speed;
         angle += curve;
         ctx.strokeStyle = color;
         ctx.beginPath();
         ctx.arc(pos[0],pos[1],size,0,2*Math.PI);
         ctx.stroke();
         window.requestAnimationFrame(draw);
      }
      window.requestAnimationFrame(draw);
    </script>
    </body>
    </html>
    View Code

          在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中呈现出如图1所示的动画效果。

     

    图1  沿圆周运动的一个圆圈

          由图1可知,圆圈运动的起点(canvas.width/2,canvas.height/2)位于运动所沿的圆周上angle==360°的位置。

    2.两个沿圆周运动的圆圈

          在画布中放置两个圆圈,两个圆圈的起点均位于画布中心(canvas.width/2,canvas.height/2),一个圆圈从所沿圆周的45°处沿圆周运动,另一个圆圈从所沿圆周的135°处沿圆周运动。编写如下的HTML代码。

    <!DOCTYPE html>
    <html>
    <head>
    <title>沿圆周运动的圆圈</title>
    </head>
    <body>
    <script>
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      document.body.appendChild(canvas);
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      ctx.beginPath();
      ctx.fillStyle = 'rgba(0, 0, 0, 1)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      var angle1 =45;
      var angle2 =135;
      var pos1 = [canvas.width/2,canvas.height/2];
      var pos2 = [canvas.width/2,canvas.height/2];
      var size = 10;
      var speed = 1;
      var curve = 0.5;
      var color1 = 'rgba(69,204,255,.95)';
      var color2 = 'rgba(255,212,50,.95)';
      function draw () 
      {
         var radians = angle1*Math.PI/180;
         pos1[0] += Math.cos(radians)* speed;
         pos1[1] += Math.sin(radians)* speed;
         angle1 += curve;
         radians = angle2*Math.PI/180;
         pos2[0] += Math.cos(radians)* speed;
         pos2[1] += Math.sin(radians)* speed;
         angle2 += curve;
         ctx.strokeStyle = color1;
         ctx.beginPath();
         ctx.arc(pos1[0],pos1[1],size,0,2*Math.PI);
         ctx.stroke();
         ctx.strokeStyle = color2;
         ctx.beginPath();
         ctx.arc(pos2[0],pos2[1],size,0,2*Math.PI);
         ctx.stroke();
     //   fade();
         window.requestAnimationFrame(draw);
      }
      function fade () 
      {
         ctx.beginPath();
         ctx.fillStyle = 'rgba(0, 0, 0, .03)';
         ctx.fillRect(0, 0, canvas.width, canvas.height);
      }
      window.requestAnimationFrame(draw);
    </script>
    </body>
    </html>
    View Code

          在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中呈现出如图2所示的动画效果。

     

    图2  两个沿圆周运动的圆圈

          为了展示圆圈运动的轨迹,我们在函数draw()的函数体中,最后一行语句前加上调用语句fade();,编写fade()函数如下:

      function fade ()

      {

         ctx.beginPath();

         ctx.fillStyle = 'rgba(0, 0, 0, .03)';

         ctx.fillRect(0, 0, canvas.width, canvas.height);

      }

          这样,圆圈运动轨迹带长尾效果。在浏览器中呈现出如图3所示的动画效果。

     

    图3  两个沿圆周运动的圆圈(带长尾效果)

    3.更多沿圆周运动的圆圈

          如果要在画布中让num个圆圈沿圆周运动呢?为此,将圆圈抽象为粒子对象Particle,该对象有圆圈在所沿圆周上的起始位置angle、圆圈运动的当前位置pos(初始值为画布中心[canvas.width/2,canvas.height/2])、圆圈大小size、运动速度speed、运动角度变化量curve和圆圈颜色color等属性;为该对象定义move和draw两个方法,分别完成圆圈的位置变化和圆圈绘制操作。

          为设定方便起见,给沿圆周运动的圆圈预设置4个参数,用变量config来表示。config.num、config.size 、config.speed和config.curve分别表示4个参数分量。其中,config.num表示画布中参与运动的圆圈个数,由它计算出圆圈在所沿圆周上的起始位置angle。

          编写的HTML文件如下。

    <!DOCTYPE html>
    <html>
    <head>
    <title>沿圆周运动的圆圈(给定4个参数)</title>
    </head>
    <body>
    <script>
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      document.body.appendChild(canvas);
      ctx.beginPath();
      ctx.fillStyle = 'rgba(0, 0, 0, 1)';
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      var particles = [];
      var colors = [ 'rgba(69,204,255,.95)', 'rgba(73,232,62,.95)',
                     'rgba(255,212,50,.95)', 'rgba(232,75,48,.95)',
                     'rgba(178,67,255,.95)' ];
      var config = {};
      config.num = 5;
      config.size = 2;
      config.speed = 1;
      config.curve = 0.5;
      createParticles() 
      window.requestAnimationFrame(draw);
      function createParticles() 
      {
         var n = config.num;
         for (var i=0; i<n; i++) 
         {
            var angle = (360/n)*(i+1);
            particles.push(new Particle(angle,colors[i%5]));
         }
      }
      function draw () 
      {
         for (var i=0; i<particles.length; i++) 
         {
            var p = particles[i];
            p.move();
            p.draw();
         }
         fade();
         window.requestAnimationFrame(draw);
      }
    
      function Particle (angle,color) 
      {
         this.angle = angle;
         this.size  = config.size;
         this.speed = config.speed;
         this.color = color;
         this.curve = config.curve;
         this.pos = [canvas.width/2, canvas.height/2];
      }  
      Particle.prototype.move = function()
      {
        this.angle += this.curve;
        var radians = this.angle*Math.PI/180;
        this.pos[0] += Math.cos(radians)*this.speed,
        this.pos[1] += Math.sin(radians)*this.speed;
      }
      Particle.prototype.draw = function () 
      {
         ctx.strokeStyle = this.color;
         ctx.beginPath();
         ctx.arc(this.pos[0],this.pos[1],this.size,0,2*Math.PI);
         ctx.stroke();
      }
      function fade () 
      {
         ctx.beginPath();
         ctx.fillStyle = 'rgba(0, 0, 0, .03)';
         ctx.fillRect(0, 0, canvas.width, canvas.height);
         ctx.fill();
      }
    </script>
    </body>
    </html>
    View Code

           在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中呈现出如图4所示的动画效果。

     

    图4  沿圆周运动的圆圈(num=5,size=2,speed = 1,curve = 0.5)

           为4个参数设定不同的值,可以呈现出不同的动画效果。给出3组不同值的设定,呈现的动画效果分别如图5、图6和图7所示。为避免图形文件过大,下列的动画过程均只录制一个片段。完整的动画演示过程请读者自己打开HTML文件运行程序观看。

     

    图5  沿圆周运动的圆圈(num=80,size=4,speed = 1,curve = 0.5)

     

    图6  沿圆周运动的圆圈(num=8,size=16,speed = 1.8,curve = 1.8)

     

    图7  沿圆周运动的圆圈(num=90,size=100,speed = 2,curve =1)

          由图4~图7可知,参数speed 和curve决定了圆圈运动的轨迹。上面代码中,各个圆圈的参数speed 和curve均相同。能否让各个运动的圆圈的参数speed 和curve不同,这样它们的运动轨迹也不同,呈现出更多的变化呢?

          一个简单的办法是让参数speed 和curve在某个区间范围内随机取值。

    例如,修改config参数的设置如下:

      config.num = 80;

      config.size = 300;

      config.speed =[1,10];

      config.curve = [-0.5,0.5];

    修改function Particle (angle,color)如下:

      function Particle (angle,color)

      {

         this.angle = angle;

         this.size  = config.size;

         this.speed = rand(config.speed[0],config.speed[1]);

         this.color = color;

         this.curve = rand(config.curve[0],config.curve[1]);

         this.pos = [canvas.width/2, canvas.height/2];

      }

    增加在区间[min,max]中取随机值的函数如下:

      function rand(min, max)

      {

         return Math.random()*(max-min)+min;

      }

           其余部分保持不变,则在浏览器窗口中呈现出如图8所示的动画效果。这个动画效果有点炫酷哟!

     

    图8  沿圆周运动的圆圈(num=80,size=300,speed =1~10,curve =-0.5~0.5)

    4.可设置参数的沿圆周运动的圆圈

           由图4~图8可知,不同的参数设定,沿圆周运动的圆圈所呈现的动画效果不同。为此,我们提供文本框输入预设数值的方式对4个参数的值进行设定,设定完成后,单击Go!按钮,按设定的参数进行动画效果的呈现。

           编写的HTML代码如下。

    <!DOCTYPE html>
    <html>
    <head>
    <title>沿圆周运动的圆圈(可设置参数)</title>
    <style>
      form 
      {
        position:absolute;
        top:0;
        left:0;
        z-index:100;
        background-color:rgba(200,200,200,.8);
        padding:8px;
        font-size:90%;
      }
      form input[type=text] 
      {
        width:30px;
        border:1px solid #000;
        text-align:center;
      }
      form button 
      {
        margin:4px auto;
        border:1px solid #000;
        display:block;
      }
    </style>
    </head>
    <body>
    <form id="settings" onsubmit="return false">
      Particles<br/>
      <input type="text" id="inBubblesMin" value="150"/>
      To 
      <input type="text" id="inBubblesMax" value="150"/><br/>
      Size<br/>
      <input type="text" id="inSizeMin" value="2"/>
      To 
      <input type="text" id="inSizeMax" value="2"/><br/>
      Speed<br/>
      <input type="text" id="inSpeedMin" value="1"/>
      To 
      <input type="text" id="inSpeedMax" value="1"/><br/>
      Curve<br/>
      <input type="text" id="inCurveMin" value=".5"/>
      To 
      <input type="text" id="inCurveMax" value=".5"/><br/>
      <button id="btnClear">Clear</button>
      <button id="btnSet">Go!</button><br/>
    </form>
    <script>
      var canvas = document.createElement('canvas');
      var ctx = canvas.getContext('2d');
      canvas.width = window.innerWidth;
      canvas.height = window.innerHeight;
      document.body.appendChild(canvas);
      var particles = [];
      var colors = [ 'rgba(69,204,255,.95)', 'rgba(73,232,62,.95)',
                     'rgba(255,212,50,.95)', 'rgba(232,75,48,.95)',
                     'rgba(178,67,255,.95)' ];
      var config = {};
      var settings = document.getElementById('settings');
      start();
      window.requestAnimationFrame(draw);
      function createParticles() 
      {
         var n = rand(config.num[0],config.num[1]);
         for (var i=0; i<n; i++) 
         {
            var angle = (360/n)*(i+1);
            particles.push(new Particle({
                angle:angle,
                size:rand(config.size[0],config.size[1]),
                speed:rand(config.speed[0],config.speed[1]),
                color:colors[i%5],
                curve:rand(config.curve[0],config.curve[1])
            }));
         }
      }
      function draw () 
      {
         for (var i=0; i<particles.length; i++) 
         {
            var p = particles[i];
            p.move();
            p.draw(ctx);
         }
         fade();
         window.requestAnimationFrame(draw);
      }
    
      function Particle (options) 
      {
         this.angle = options.angle;
         this.size  = options.size;
         this.speed = options.speed;
         this.color = options.color;
         this.curve = options.curve;
         this.pos = [canvas.width/2, canvas.height/2];
      }  
      Particle.prototype.move = function()
      {
        this.angle += this.curve;
        var radians = this.angle*Math.PI/180;
        this.pos[0] += Math.cos(radians)*this.speed,
        this.pos[1] += Math.sin(radians)*this.speed;
      }
      Particle.prototype.draw = function (ctx) 
      {
         ctx.strokeStyle = this.color;
         ctx.beginPath();
         ctx.arc(this.pos[0],this.pos[1],this.size,0,2*Math.PI);
         ctx.stroke();
      }
    
      function fade () 
      {
         ctx.beginPath();
         ctx.fillStyle = 'rgba(0, 0, 0, .03)';
         ctx.fillRect(0, 0, canvas.width, canvas.height);
         ctx.fill();
      }
      function clear () 
      {
         ctx.beginPath();
         ctx.fillStyle = 'rgba(0, 0, 0, 1)';
         ctx.fillRect(0, 0, canvas.width, canvas.height);
         ctx.fill();
         particles.length = 0;
      }
      function start() 
      {
            config.num = [parseFloat(settings.inBubblesMin.value),
                          parseFloat(settings.inBubblesMax.value) ];
            config.size = [parseFloat(settings.inSizeMin.value),
                          parseFloat(settings.inSizeMax.value)];
            config.speed = [parseFloat(settings.inSpeedMin.value),
                          parseFloat(settings.inSpeedMax.value)];
            config.curve = [parseFloat(settings.inCurveMin.value),
                          parseFloat(settings.inCurveMax.value)];
            createParticles();
      }
      settings.btnSet.addEventListener("click", start);
      settings.btnClear.addEventListener("click", clear);
      function rand(min, max) 
      {
         return Math.random()*(max-min)+min;
      }
    </script>
    </body>
    </html>
    View Code

          在浏览器中打开包含这段HTML代码的html文件,可以在浏览器窗口中呈现出如图9所示的动画效果。

     

    图9  沿圆周运动的圆圈(单击一次Go!按钮)

           在页面中,单击Clear按钮,会清屏,同时置粒子数组的长度为0,相当于页面中不再有沿圆周运动的圆圈。

           单击Go!按钮,会读取设置的参数值,同时调用createParticles();向粒子数组中添加运动的圆圈。注意:是添加,若数组中原来有运动的圆圈,则原来运动的圆圈会继续运动。这样,多次单击Go!按钮,会呈现出更多有变化的动画效果。

           例如,图9的动画效果是150个运动的圆圈构成一个大圆环收缩效果。若按一定时间间隔单击两次Go!按钮,应该会呈现出2个大圆环交替收缩的动画效果,如图10所示。

     

    图10  沿圆周运动的圆圈(单击两次Go!按钮)

        多次单击Go!按钮添加运动圆圈的功能设定很有意思了。这意味着我们可以将上面的动画效果进行组合。图10的动画效果实质是两个图9所示动画效果的组合。

           例如,设定num=150,size=2,speed = 1,curve = 0.5后,单击“Go!”按钮,呈现出如图9所示的动画效果;再设定num=8,size=16,speed = 1.8,curve = 1.8,单击Go!按钮(呈现如图6所示的动画效果)后,图6和图9的动画效果组合起来,呈现出如图11所示的动画效果。

     

    图11  两种动画效果的组合

  • 相关阅读:
    mysql timeout expired处理
    Git学习笔记(0)-错误汇总
    auto_ptr源码剖析
    谈谈工作中遇到的系统优化问题
    js 面向对象
    js API
    js 闭包
    js 重载(overload)
    css 文本单行、多行超出省略
    es6 字符串String的扩展
  • 原文地址:https://www.cnblogs.com/cs-whut/p/13742844.html
Copyright © 2011-2022 走看看