1. 首页
  2. 前端

使用canvas实现动态绚丽的线条动画实例2

使用canvas实现动态绚丽的线条动画实例2

Canvas是html5里面的一个非常实用的标签,Canvas结合javascript可以实现超炫的动画和图形。当然,canvas只有结合强大的javascript,才能发挥出其惊人的特效。要学好Canvas也不是件容易的事。各位小伙伴儿们如果有空可以研究下canvas方面的API,多多练习,慢慢的也会成为大神。

下面再为大家分享一个关于canvas的经典动态绚丽线条动画案例。

html部分如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>HTML5 Canvas流动线条动画</title>
    <link rel="stylesheet" href="css/style.css">
  </head>
  <body>
    <div id="holder"></div>
    <scriptsrc="js/index.js"></script>
  </body>
</html>

style.css文件如下:

* {margin: 0;padding: 0;}
body { background-color: #000; overflow: hidden;}
#holder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

index.js文件如下:

(function () {
  var pi = Math.PI;
  var pi2 = 2 * Math.PI;
  this.Waves = function (holder, options) {
    var Waves = this;
    Waves.options = extend(options || {}, {
      resize: false,
      rotation: 45,
      waves: 5,
      width: 100,
      hue: [11, 14],
      amplitude: 0.5,
      background: true,
      preload: true,
      speed: [0.004, 0.008],
      debug: false,
      fps: false,
    });
    Waves.waves = [];
    Waves.holder = document.querySelector(holder);
    Waves.canvas = document.createElement('canvas');
    Waves.ctx = Waves.canvas.getContext('2d');
    Waves.holder.appendChild(Waves.canvas);
    Waves.hue = Waves.options.hue[0];
    Waves.hueFw = true;
    Waves.stats = new Stats();
    Waves.resize();
    Waves.init(Waves.options.preload);
    if (Waves.options.resize)
      window.addEventListener('resize', function () {
        Waves.resize();
      }, false);
  };
  Waves.prototype.init = function (preload) {
    var Waves = this;
    var options = Waves.options;
    for (var i = 0; i < options.waves; i++)
      Waves.waves[i] = new Wave(Waves);
    if (preload) Waves.preload();
  };
  Waves.prototype.preload = function () {
    var Waves = this;
    var options = Waves.options;
    for (var i = 0; i < options.waves; i++) {
      Waves.updateColor();
      for (var j = 0; j < options.width; j++) {
        Waves.waves[i].update();
      }
    }
  };
  Waves.prototype.render = function () {
    var Waves = this;
    var ctx = Waves.ctx;
    var options = Waves.options;
    Waves.updateColor();
    Waves.clear();
    if (Waves.options.debug) {
      ctx.beginPath();
      ctx.strokeStyle = '#f00';
      ctx.arc(Waves.centerX, Waves.centerY, Waves.radius, 0, pi2);
      ctx.stroke();
    }
    if (Waves.options.background) {
      Waves.background();
    }
    each(Waves.waves, function (wave, i) {
      wave.update();
      wave.draw();
    });
  };
  Waves.prototype.animate = function () {
    var Waves = this;
    Waves.render();
    if (Waves.options.fps) {
      Waves.stats.log();
      Waves.ctx.font = '12px Arial';
      Waves.ctx.fillStyle = '#fff';
      Waves.ctx.fillText(Waves.stats.fps() + ' FPS', 10, 22);
    }
    window.requestAnimationFrame(Waves.animate.bind(Waves));
  };
  Waves.prototype.clear = function () {
    var Waves = this;
    Waves.ctx.clearRect(0, 0, Waves.width, Waves.height);
  };
  Waves.prototype.background = function () {
    var Waves = this;
    var ctx = Waves.ctx;
    var gradient = Waves.ctx.createLinearGradient(0, 0, 0, Waves.height);
    gradient.addColorStop(0, '#000');
    gradient.addColorStop(1, Waves.color);
    ctx.fillStyle = gradient;
    ctx.fillRect(0, 0, Waves.width, Waves.height);
  };
  Waves.prototype.resize = function () {
    var Waves = this;
    var width = Waves.holder.offsetWidth;
    var height = Waves.holder.offsetHeight;
    Waves.scale = window.devicePixelRatio || 1;
    Waves.width = width * Waves.scale;
    Waves.height = height * Waves.scale;
    Waves.canvas.width = Waves.width;
    Waves.canvas.height = Waves.height;
    Waves.canvas.style.width = width + 'px';
    Waves.canvas.style.height = height + 'px';
    Waves.radius = Math.sqrt(Math.pow(Waves.width, 2) + Math.pow(Waves.height, 2)) / 2;
    Waves.centerX = Waves.width / 2;
    Waves.centerY = Waves.height / 2;
    //Waves.radius /= 2; // REMOVE FOR FULLSREEN
  };
  Waves.prototype.updateColor = function () {
    var Waves = this;
    Waves.hue += (Waves.hueFw) ? 0.01 : -0.01;
    if (Waves.hue > Waves.options.hue[1] && Waves.hueFw) {
      Waves.hue = Waves.options.hue[1];
      Waves.Waves = false;
    } else if (Waves.hue < Waves.options.hue[0] && !Waves.hueFw) {
      Waves.hue = Waves.options.hue[0];
      Waves.Waves = true;
    }
    var a = Math.floor(127 * Math.sin(0.3 * Waves.hue + 0) + 128);
    var b = Math.floor(127 * Math.sin(0.3 * Waves.hue + 2) + 128);
    var c = Math.floor(127 * Math.sin(0.3 * Waves.hue + 4) + 128);
    Waves.color = 'rgba(' + a + ',' + b + ',' + c + ', 0.1)';
  };

  function Wave(Waves) {
    var Wave = this;
    var speed = Waves.options.speed;
    Wave.Waves = Waves;
    Wave.Lines = [];
    Wave.angle = [
      rnd(pi2),
      rnd(pi2),
      rnd(pi2),
      rnd(pi2)
    ];

    Wave.speed = [
      rnd(speed[0], speed[1]) * rnd_sign(),
      rnd(speed[0], speed[1]) * rnd_sign(),
      rnd(speed[0], speed[1]) * rnd_sign(),
      rnd(speed[0], speed[1]) * rnd_sign(),
    ];
    return Wave;
  }

  Wave.prototype.update = function () {
    var Wave = this;
    var Lines = Wave.Lines;
    var color = Wave.Waves.color;
    Lines.push(new Line(Wave, color));
    if (Lines.length > Wave.Waves.options.width) {
      Lines.shift();
    }
  };

  Wave.prototype.draw = function () {
    var Wave = this;
    var Waves = Wave.Waves;
    var ctx = Waves.ctx;
    var radius = Waves.radius;
    var radius3 = radius / 3;
    var x = Waves.centerX;
    var y = Waves.centerY;
    var rotation = dtr(Waves.options.rotation);
    var amplitude = Waves.options.amplitude;
    var debug = Waves.options.debug;
    var Lines = Wave.Lines;
    each(Lines, function (line, i) {
      if (debug && i > 0) return;
      var angle = line.angle;
      var x1 = x - radius * Math.cos(angle[0] * amplitude + rotation);
      var y1 = y - radius * Math.sin(angle[0] * amplitude + rotation);
      var x2 = x + radius * Math.cos(angle[3] * amplitude + rotation);
      var y2 = y + radius * Math.sin(angle[3] * amplitude + rotation);
      var cpx1 = x - radius3 * Math.cos(angle[1] * amplitude * 2);
      var cpy1 = y - radius3 * Math.sin(angle[1] * amplitude * 2);
      var cpx2 = x + radius3 * Math.cos(angle[2] * amplitude * 2);
      var cpy2 = y + radius3 * Math.sin(angle[2] * amplitude * 2);
      ctx.strokeStyle = (debug) ? '#fff' : line.color;
      ctx.beginPath();
      ctx.moveTo(x1, y1);
      ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x2, y2);
      ctx.stroke();
      if (debug) {
        ctx.strokeStyle = '#fff';
        ctx.globalAlpha = 0.3;
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(cpx1, cpy1);
        ctx.stroke();
        ctx.beginPath();
        ctx.moveTo(x2, y2);
        ctx.lineTo(cpx2, cpy2);
        ctx.stroke();
        ctx.globalAlpha = 1;
      }
    });
  };

  function Line(Wave, color) {
    var Line = this;
    var angle = Wave.angle;
    var speed = Wave.speed;
    Line.angle = [
      Math.sin(angle[0] += speed[0]),
      Math.sin(angle[1] += speed[1]),
      Math.sin(angle[2] += speed[2]),
      Math.sin(angle[3] += speed[3])
    ];
    Line.color = color;
  }

  function Stats() {
    this.data = [];
  }

  Stats.prototype.time = function () {
    return (performance || Date)
      .now();
  };
  Stats.prototype.log = function () {
    if (!this.last) {
      this.last = this.time();
      return 0;
    }
    this.new = this.time();
    this.delta = this.new - this.last;
    this.last = this.new;
    this.data.push(this.delta);
    if (this.data.length > 10)
      this.data.shift();
  };

  Stats.prototype.fps = function () {
    var fps = 0;
    each(this.data, function (data, i) {
      fps += data;
    });
    return Math.round(1000 / (fps / this.data.length));
  };

  function each(items, callback) {
    for (var i = 0; i < items.length; i++) {
      callback(items[i], i);
    }
  }

  function extend(options, defaults) {
    for (var key in options)
      if (defaults.hasOwnProperty(key))
        defaults[key] = options[key];
    return defaults;
  }

  function dtr(deg) {
    return deg * pi / 180;
  }

  function rtd(rad) {
    return rad * 180 / pi;
  }

  function diagonal_angle(w, h) {
    var a = Math.atan2(h, w) * 1.27325;
    return a;
  }

  function rnd(a, b) {
    if (arguments.length == 1)
      return Math.random() * a;
    return a + Math.random() * (b - a);
  }

  function rnd_sign() {
    return (Math.random() > 0.5) ? 1 : -1;
  }
})();

var waves = new Waves('#holder', {
  fps: true,
  waves: 3,
  width: 200,
});
waves.animate();

 

原创文章,作者:Ferrycoln,如若转载,请注明出处:https://ms200.cn/archives/900

发表评论

邮箱地址不会被公开。 必填项已用*标注

联系我们

在线咨询:点击这里给我发消息

邮件:499661635@qq.com.com

工作时间:周一至周五,9:30-18:30

QR code