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;
}
</style>

 
 
 
</head>

<body >

 
     
<script >
"use strict";

window.addEventListener("load", function () {
  const DIST_BRIDSON_MIN = 0.1; // size of pattern - relative to canvas size
  const DIST_BRIDSON_MAX = 0.2;
  const SPEED = 0.6; // must be > 0. May be tuned for a better halo effect, depending on size and FPS

  let canv, ctx; // canvas and context
  let maxx, maxy; // canvas dimensions
  let tr, distBridson;
  let displayCycle;
  let polygons;
  let gr;

  // for animation
  let messages;

  // 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 matan2 = Math.atan2;

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

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

  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
  }
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  /*    ============================================================================
  This hash function is based upon Johannes Baagoe's carefully designed and efficient hash
  function for use with JavaScript.  It has a proven "avalanche" effect such
  that every bit of the input affects every bit of the output 50% of the time,
  which is good.        See: http://baagoe.com/en/RandomMusings/hash/avalanche.xhtml
  ============================================================================
  */
  /* This function returns a hash function depending on a seed.
       if no seed is provided (or a falsy value), Math.random() is used.
      The returned function always returns the same number in the range [0..1[ for the
      same value of the argument. This argument may be a String or a Number or anything else
      which can be 'toStringed'
      Two returned functions obtained with two equal seeds are equivalent.
      */


  function hashFunction(seed) {
    let n0 = 0xefc8249d;
    let n = n0;
    mash(seed || Math.random()); // pre-compute n for seed
    n0 = n; //

    function mash(data) {
      data = data.toString() + "U";
      n = n0;
      for (let i = 0; i < data.length; i++) {
        n += data.charCodeAt(i);
        var h = 0.02519603282416938 * n;
        n = h >>> 0;
        h -= n;
        h *= n;
        n = h >>> 0;
        h -= n;
        n += h * 0x100000000; // 2^32
      } // for
      return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
    } // mash
    return mash;
  } // hashFunction(seed)

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

  function Noise1D(period, min = 0, max = 1, hash) {
    /* returns a 1D noise function.
           the (mandatory) hash function must return a value between 0 and 1. The hash function
           will be called with an integer number for a parameter.
          the returned function takes one parameter, and will always return the same value if called with the same parameter
          period should be > 1. The bigger period is, the smoother the output noise is
         suggestion : the hash parameter could be a function returned from a call to hashFunction above
         */



    let currx, y0, y1; // cached valued, to reduce number of calls to 'hash'
    let phase = hash(0); // to shift the phase of different generators between each other;

    return function (x) {
      let xx = x / period + phase;
      let intx = mfloor(xx);

      if (intx - 1 === currx) {
        // next integer interval
        ++currx;
        y0 = y1;
        y1 = min + (max - min) * hash(currx + 1);
      } else if (intx !== currx) {
        // unrelated interval
        currx = intx;
        y0 = min + (max - min) * hash(currx);
        y1 = min + (max - min) * hash(currx + 1);
      }
      let frac = xx - currx;
      let z = (3 - 2 * frac) * frac * frac;
      return z * y1 + (1 - z) * y0;
    };
  } // Noise1D
  /* example : noise = Noise1D (100, 0, maxy, hashFunction(seed));
   */

  function arrayShuffle(array) {
    /* randomly changes the order of items in an array
           only the order is modified, not the elements
        */
    let k1, temp;
    for (let k = array.length - 1; k >= 1; --k) {
      k1 = intAlea(0, k + 1);
      temp = array[k];
      array[k] = array[k1];
      array[k1] = temp;
    } // for k
    return array;
  } // arrayShuffle
  // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  function lerp(p0, p1, alpha) {
    return {
      x: (1 - alpha) * p0.x + alpha * p1.x,
      y: (1 - alpha) * p0.y + alpha * p1.y };

  }
  //------------------------------------------------------------------------
  //------------------------------------------------------------------------

  function generatePoints(t) {
    return t.points.map(p => ({ x: p.x, y: p.y })); // shallow copy
  } // generate points

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

  class SortedArray {
    /* creates a sorted array of any kind of things, by intersting them into an initially empty array
           the comparison function used for sorting is given to the constructor
           Things are inserted using .insert method
           sorted array is in the .tb property of the instance
        */
    /*
        the indexOf property lets you know if thing already existed according to fCompar, and at what index
        just use doInsert(no parameters) after indexOf to insert thing at found (not -1) index
        */

    /* CAUTION : if duplicates are allowed, indexOf is NOT garanteed to return the index of actual thing - only a thing
              which returns 0 when compared with given thing. Use regular Array.indexOf on instance.tb instead.
        */
    constructor(fCompar, keepDuplicates = false) {
      /* fCompar is the function which will be called to compare the things that will be inserted
          in  this.tb
              fCompar(a,b) must return  number < 0 if a must be placed before b
              == 0 if a and b are considered equal
              > 0 if a must be placed after b
          */
      this.tb = [];
      this.fCompar = fCompar;
      this.keepDuplicates = keepDuplicates;
    }

    indexOf(thing) {
      this.thing = thing;
      // search for place to insert thing, using comparison function this.fCompar
      // if found, returns the index of thing in this.tb, else returns -1
      // sets this.insertAt for future insertion

      let cmp;
      if (this.tb.length == 0) {
        this.insertAt = 0;
        return -1;
      }
      let a = 0,
      c = this.tb.length - 1;
      let b;

      do {
        b = Math.floor((a + c) / 2);
        cmp = this.fCompar(this.tb[b], thing);
        switch (true) {
          case cmp < 0: // thing after b
            if (b == c) {
              // beyond c
              this.insertAt = c + 1;
              return -1;
            }
            if (a == b) ++b; // not to stay on same interval, if its length is 1 or 2
            a = b; // after b : search (b, c) now
            break;
          case cmp == 0:
            this.insertAt = b;
            return b; // found !

          default:
            //thing before b
            if (b == a) {
              // before a
              this.insertAt = a;
              return -1;
            }
            c = b; // search (a, b) now
        }
      } while (true);
    } // indexOf

    doInsert() {
      // DO NOT CALL TWICE WITHOUT getting new (!= -1) indexOf
      this.tb.splice(this.insertAt, 0, this.thing);
    }

    insert(thing) {
      /* inserts thing */
      if (this.indexOf(thing) != -1 && !this.keepDuplicates) return; // already exists and refused
      this.tb.splice(this.insertAt, 0, thing);
    }}
  // class SortedArray
  //------------------------------------------------------------------------
  class Edge {
    constructor(p0, p1) {
      if (p0.kp <= p1.kp) {
        this.p0 = p0;
        this.p1 = p1;
      } else {
        this.p0 = p1;
        this.p1 = p0;
      }
      this.tris = []; // to record up to 2 triangles attached to this edge
    }

    attachTriangle(tri) {
      // includes a triangle in and edge's tris array
      // AND includes itself in this triangle's edges array
      // AND more

      if (!this.p0.tris.includes(tri)) this.p0.tris.push(tri);
      if (!this.p1.tris.includes(tri)) this.p1.tris.push(tri);

      if (!this.p0.edges.includes(this)) this.p0.edges.push(this);
      if (!this.p1.edges.includes(this)) this.p1.edges.push(this);

      if (tri.a == this.p0) {
        if (tri.b == this.p1) {
          this.tris[0] = tri;
          tri.edges[0] = this;
        } else {
          this.tris[1] = tri;
          tri.edges[2] = this;
        }
        return;
      }
      if (tri.b == this.p0) {
        if (tri.c == this.p1) {
          this.tris[0] = tri;
          tri.edges[1] = this;
        } else {
          this.tris[1] = tri;
          tri.edges[0] = this;
        }
        return;
      }
      if (tri.c == this.p0) {
        if (tri.a == this.p1) {
          this.tris[0] = tri;
          tri.edges[2] = this;
        } else {
          this.tr.........完整代码请登录后点击上方下载按钮下载查看

网友评论0