canvas卷积动画效果代码

代码语言:html

所属分类:动画

代码描述:canvas卷积动画效果代码

代码标签: canvas 卷积 动画

下面为部分代码预览,完整代码请点击下载或在bfwstudio webide中打开

<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">
  

  
  
  
<style>
body {
            font-family: Arial, Helvetica, "Liberation Sans", FreeSans, sans-serif;
            background-color: #000;
            margin: 0;
            padding: 0;
            border-width: 0;
            cursor: pointer;
            caret-color: transparent;
        }
</style>




</head>

<body >
  

  
      <script >
window.addEventListener("load", function () {
  "use strict";

  let canv, ctx; // canvas and context
  let maxx, maxy; // canvas dimensions

  let radius, x0, y0, x1, y1, nbPts, theta;
  let grid, nbx, nby;

  // for animation
  let events;
  let ui, uiv;
  let rotSpeed = 0.3 / 1000; // rotation speed, in radians / ms
  let rotColor = "#0ff";

  // shortcuts for Math.
  const mrandom = Math.random;
  const mfloor = Math.floor;
  const mround = Math.round;
  const mceil = Math.ceil;
  const mabs = Math.abs;
  const mmin = Math.min;
  const mmax = Math.max;

  const mPI = Math.PI;
  const mPIS2 = Math.PI / 2;
  const mPIS3 = Math.PI / 3;
  const m2PI = Math.PI * 2;
  const m2PIS3 = Math.PI * 2 / 3;
  const msin = Math.sin;
  const mcos = Math.cos;
  const mtan = Math.tan;
  const matan2 = Math.atan2;

  const mhypot = Math.hypot;
  const msqrt = Math.sqrt;

  const sqrt3 = msqrt(3);
  const hsqrt3 = msqrt(3) / 2;

  //------------------------------------------------------------------------

  function alea(mini, maxi) {
    // random number in given range
    if (typeof maxi == 'undefined') return mini * mrandom(); // range 0..mini
    return mini + mrandom() * (maxi - mini); // range mini..maxi
  }
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  function intAlea(mini, maxi) {
    // random integer in given range (mini..maxi - 1 or 0..mini - 1)
    //
    if (typeof maxi == 'undefined') return mfloor(mini * mrandom()); // range 0..mini - 1
    return mini + mfloor(mrandom() * (maxi - mini)); // range mini .. maxi - 1
  }

  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  class CircularNoise {
    constructor(period, amplitude, initTime = 0) {
      /* period should be > 0, and great in comparision to the time interval of successive calls
      "great" means at least 10 times, though this limit is not strict
      Depending on usage, it may be useful to think it represents milliseconds
      "amplitude" is the maximum change (+ or -) of output in an interval of "period" - should be << 1 since autput is in range 0-1
      */
      this.prevTime = initTime;
      this.period = period;
      this.amplitude = amplitude;

      this.currentPeriod = (0.75 + 0.5 * Math.random()) * this.period; // 1 +/- 0.25
      this.phase = Math.random(); // phase is going from 0 1
      this.v0 = Math.random();
      this.v1 = this.v0 + this.amplitude * 2 * (Math.random() - 0.5);
    }

    value(t) {
      // returns a number in range 0-1
      let dt = t - this.prevTime; // supposed to be > 0, since time is increasing
      let dPhase = dt / this.currentPeriod; // supposed to be < 1
      this.phase += dPhase;
      if (dPhase > 1) {
        this.currentPeriod = (0.75 + 0.5 * Math.random()) * this.period;
        this.phase %= 1;
        this.v0 = this.v1 % 1;
        while (this.v0 < 0) this.v0 += 1;
        this.v1 = this.v0 + this.amplitude * 2 * (Math.random() - 0.5);
      }
      this.prevTime = t;
      let ph = (3 - 2 * this.phase) * this.phase * this.phase;
      return this.v1 * this.phase + this.v0 * (1 - this.phase);
    }}

  //------------------------------------------------------------------------
  // for curves inside circles
  //------------------------------------------------------------------------

  function calcAlpha(angle, beta) {

    const mc = mabs(mcos(angle / 2));
    if (mc < 1e-3) return 0.4845;
    return 1.3333333333333333333 * (1 - beta / mc);

  } // calcAlpha

  function arcPerp(th0, th1, alpha) {

    /* for a unity circle centered in (0, 0) returns values for a bezier cubic curve
    perpendicular to circle
    connecting point at angle th0 to point at angle th1 at distance alpha from centre
    */
    let angle = mabs(th0 - th1);
    if (angle > mPI) angle = m2PI - angle;

    alpha = 1 - calcAlpha(angle, alpha);
    const mc0 = mcos(th0);
    const ms0 = msin(th0);
    const mc1 = mcos(th1);
    const ms1 = msin(th1);

    return [{ x: mc0, y: ms0 },
    { x: alpha * mc0, y: alpha * ms0 },
    { x: alpha * mc1, y: alpha * ms1 },
    { x: mc1, y: ms1 }];
  }

  function autoArcPerp(th0, th1, sect) {
    /* like arc, but alpha is evaluated automatically so as to have :
        - angle == 0 => alpha = 1
        - angle == sect => alpha = small
         this "small" comes from the "z" coefficient below. Experience shows that z = 1 for sect == PI, and z = 0.8 for sect == PI / 3 are suitable
    */

    let angle = mabs(th0 - th1) % m2PI; // 0 .. 2 pi
    if (angle > mPI) angle = m2PI - angle; // 0 .. pi
    const z = (1 * (sect - mPI / 3) + 0.8 * (mPI - sect)) / (mPI - mPI / 3); // 0.8 for sect==mPI/3, 1 for sect == mPI
    let alpha = 1 - z * angle / sect;
    alpha = 1.0 - calcAlpha(angle, alpha);
    const mc0 = mcos(th0);
    const ms0 = msin(th0);
    const mc1 = mcos(th1);
    const ms1 = msin(th1);

    return [{ x: mc0, y: ms0 },
    { x: alpha * mc0, y: alpha * ms0 },
    { x: alpha * mc1, y: alpha * ms1 },
    { x: mc1, y: ms1 }];
  }

  function scaleArc(arc, xc, yc, radius) {

    return arc.map(p => ({ x: p.x * radius + xc, y: p.y * radius + yc })); // apply radius and position of center
  }

  //------------------------------------------------------------------------
  // for curves between circles
  //------------------------------------------------------------------------
  function normalizedRadiiConnection(anglec, angle, alpha) {
    /* connection line between two tangent circles of radius 1
    the first circle has its center in (0,0)
    the second circle has its center in (cos(anglec),sin(anglec))
     angle is a direction (0 = horizontally rightwards, pi/2 = downwards)
    alpha is a factor : 0 => Bézier curve will be a straignt line, 1 => Bézier curve will be (almost) a circle arc
    alpha > 1 is possible, alpha < 0 is not
    The curve connects "smoothly" the radius from first circle in direction alpha, to the radius in second circle symmetrical of (radius in c1)
    with respect to the symmetry axis of the two circles
    */

    const dx = mcos(anglec);
    const dy = msin(anglec);
    const ca = mcos(angle);
    const sa = msin(angle);
    const c = ca * dx + sa * dy; // if < 0 , problems are to be expected...
    const cu = c;
    const s = sa * dx - ca * dy;
    const su = s;
    const cb = dx;
    const sb = dy;
    const p0 = { x: ca, y: sa };
    const ddx = -c * cb - s * sb;
    const ddy = -c * sb + s * cb;
    const p3 = {
      x: 2 * dx + ddx,
      y: 2 * dy + ddy };


    const rad = msqrt((1 - cu) / (1 + cu));
    const beta = rad * mabs(mabs(su) < 0.01 ? 2 * su * alpha / 3 : 1.3333333333 * alpha * (1 - cu) / su); // distance between control points and ends of arc
    const p1 = { x: p0.x + beta * ca, y: p0.y + beta * sa };
    const p2 = {
      x: p3.x + beta * ddx,
      y: p3.y + beta * ddy };

    return [p0, p1, p2, p3];
  }

  //------------------------------------------------------------------------

  class Circle {
    constructor(kx, ky) {
      this.kx = kx;
      this.ky = ky;
      this.xc = maxx / .........完整代码请登录后点击上方下载按钮下载查看

网友评论0