Vector2打造一个跟随鼠标移动的深海奇异生物效果代码

代码语言:html

所属分类:动画

代码描述:Vector2打造一个跟随鼠标移动的深海奇异生物效果代码

代码标签: 跟随 鼠标 移动 深海 奇异 生物 效果

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

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

<head>

  <meta charset="UTF-8">

<link type="text/css" rel="stylesheet" href="//repo.bfw.wiki/bfwrepo/css/reset.min.css">
  
  
<style>
body {
  background: black;
}

.canvas {
  mix-blend-mode: screen;
}

.canvas, .background, .overlay {
  position: absolute;
  width: 100vw;
  height: 100vh;
}


</style>



</head>

<body >
  <canvas class="background"></canvas>
<canvas class="canvas"></canvas>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/Vector2.min.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/perlin-min.js"></script>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/dat.gui-min.js"></script>
      <script >
"use strict";

const {
  abs,
  acos,
  asin,
  atan,
  atan2,
  ceil,
  cos,
  max,
  min,
  PI,
  pow,
  random,
  round,
  sin,
  sqrt,
  tan } =
Math;
const HALF_PI = 0.5 * PI;
const QUART_PI = 0.25 * PI;
const TAU = 2 * PI;
const TO_RAD = PI / 180;
const G = 6.67 * pow(10, -11);
const EPSILON = 2.220446049250313e-16;
const rand = n => n * random();
const randIn = (_min, _max) => rand(_max - _min) + _min;
const randRange = n => n - rand(2 * n);
const fadeIn = (t, m) => t / m;
const fadeOut = (t, m) => (m - t) / m;
const fadeInOut = (t, m) => {
  let hm = 0.5 * m;
  return abs((t + hm) % m - hm) / hm;
};
const dist = (x1, y1, x2, y2) => sqrt(pow(x2 - x1, 2) + pow(y2 - y1, 2));
const angle = (x1, y1, x2, y2) => atan2(y2 - y1, x2 - x1);
const lerp = (a, b, t) => (1 - t) * a + t * b;
const clamp = (n, _min, _max) => min(max(n, _min), _max);
const norm = (n, _min, _max) => (n - _min) / (_max - _min);
const floor = n => n | 0;
const fract = n => n - floor(n);
const vh = p => p * window.innerHeight * 0.01;
const vw = p => p * window.innerWidth * 0.01;
const vmin = p => min(vh(p), vw(p));
const vmax = p => max(vh(p), vw(p));
const intToRGBA = n => {
  let r, g, b, a;

  n >>>= 0;

  r = (n & 0xff000000) >>> 24;
  g = (n & 0xff0000) >>> 16;
  b = (n & 0xff00) >>> 8;
  a = (n & 0xff) / 255;

  return `rgba(${[r, g, b, a].join()})`;
};
const nearestMultiple = (n, d) => n - n % d;
const drawTypes = {
  FILL: 'fill',
  STROKE: 'stroke' };

const textAlignTypes = {
  CENTER: 'center',
  END: 'end',
  LEFT: 'left',
  RIGHT: 'right',
  START: 'start' };

const textBaselineTypes = {
  ALPHABETIC: 'alphabetic',
  BOTTOM: 'bottom',
  HANGING: 'hanging',
  MIDDLE: 'middle',
  TOP: 'top' };


Array.prototype.lerp = function (t = [], a = 0) {
  this.forEach((n, i) => this[i] = lerp(n, t[i], a));
};

Float32Array.prototype.get = function (i = 0, n = 0) {
  const t = i + n;

  let r = [];

  for (; i < t; i++) {
    r.push(this[i]);
  }

  return r;
};

class PropsArray {
  constructor(count = 0, props = [], type = 'float') {
    this.count = count;
    this.props = props;
    this.spread = props.length;
    this.values = type === 'float' ?
    new Float32Array(count * props.length) :
    new Uint32Array(count * props.length);
  }
  get length() {
    return this.values.length;
  }
  set(a = [], i = 0) {
    this.values.set(a, i);
  }
  setMap(o = {}, i = 0) {
    this.set(Object.values(o), i);
  }
  get(i = 0) {
    return this.values.get(i, this.spread);
  }
  getMap(i = 0) {
    return this.get(i).reduce(
    (r, v, i) => ({
      ...r,
      ...{ [this.props[i]]: v } }),

    {});

  }
  forEach(cb) {
    let i = 0;

    for (; i < this.length; i += this.spread) {
      cb(this.get(i), i, this);
    }
  }
  map(cb) {
    let i = 0;

    for (; i < this.length; i += this.spread) {
      this.set(cb(this.get(i), i, this), i);
    }
  }
  async *read() {
    let i = 0;

    for (; i < this.length; i += this.spread) {
      yield { index: i, value: this.get(i) };
    }
  }}


function createOffscreenCanvas(width, height) {
  let _canvas;

  if (typeof OffscreenCanvas !== undefined) {
    _canvas = new OffscreenCanvas(parseFloat(width), parseFloat(height));
  } else {
    _canvas = createCanvas(width, height);
  }

  return _canvas;
}

function createCanvas(width, height) {
  const canvas = document.createElement('canvas');

  canvas.width = width;
  canvas.height = height;

  return canvas;
}

function createContext2D(width = innerWidth, height = innerHeight, contextAttributes) {
  return createCanvas(width, height).getContext('2d', contextAttributes);
}

function createOffscreenContext2D(width = innerWidth, height = innerHeight, contextAttributes) {
  return createOffscreenCanvas(width, height).getContext('2d', contextAttributes);
}

function createRenderingContext(width, height) {
  const contextAttributes = {
    desynchronized: true,
    willReadFrequently: true };


  const ctx = createContext2D(width, height, contextAttributes);
  const buffer = createOffscreenContext2D(width, height, contextAttributes);

  ctx.canvas.style.position = 'absolute';

  document.body.appendChild(ctx.canvas);

  return {
    buffer,
    ctx };

}

let canvas, background, creature, mouse;
let tick = 0;
let opts = {
  animation: {
    breathe: true,
    spin: true,
    followMouse: true,
    type: "mobius",
    speed: 4 },

  motion: {
    rigidity: parseFloat(rand(1).toFixed(1)),
    responsiveness: parseFloat(rand(1).toFixed(1)) },

  color: {
    startHue: rand(360),
    glow: 0.4 },

  structure: {
    baseRadius: round(rand(20)) + 20,
    armCount: round(rand(15)) + 15,
    segmentLength: 18,
    segmentMin: 6,
    segmentMax: 28,
    segmentNum: () =>
    Math.round(Math.random() * (opts.structure.segmentMax - opts.structure.segmentMin) + opts.structure.segmentMin) },

  noise: {
    enabled: true,
    strength: 0.5,
    type: "rough" },

  reset: () => {
    noise.seed(Math.round(2000 * Math.random()));
    creature = new Creature(opts.structure.armCount);
    ctx.clearRect(0, 0, canvas.dimensions.x, canvas.dimensions.y);
  } };


class Mouse {
  constructor() {
    this.hover = false;
    this.position = new Vector2(
    0.5 * window.innerWidth,
    0.5 * window.innerHeight);

    this.animationTarget = new Vector2(
    this.position.x, this.position.y);

    this.animate = {
      random: () => {
        if (tick % 180 === 0) {
          this.animationTarget.x = Math.random() * canvas.dimensions.x;
          this.animationTarget.y = Math.random() * canvas.dimensions.y;
        }
        this.position.lerp(this.animationTarget, 0.35);
      },
      mobius: () => {
        this.animationTarget.lerp({
          x: 0.5 * canvas.dimensions.x + 0.35 * canvas.dimensions.x * -cos(tick * 0.0125),
          y: 0.5 * canvas.dimensions.y + 0.35 * canvas.dimensions.y * -sin(tick * 0.025) },
        0.85);
        this.position.lerp(this.animationTarget, 0.65);
      },
      idle: () => {
        this.animationTarget.x = 0.5 * canvas.dimensions.x;
        this.animationTarget.y = 0.5 * canvas.dimensions.y;
        this.position.lerp(this.animationTarget, 1);
      } };

  }}


class Segment {
  constructor(x, y, len, angle, parent, index) {
    this.index = index;
    switch (opts.noise.type) {
      case "rough":
        this.tick = Math.round(Math.random() * 10 * opts.structure.armCount);
        break;
      case "even":
        this.tick = 0;
        break;
      case "gradient":
        this.tick = index * 200;
        break;
      case "fractal":
        this.tick = noise.simplex3(x * 0.015, y * 0.015, index * 0.015) * 200;
        break;
      default:
        break;}

    this.jointSize = Math.random() * 2.5;
    this.parent = parent;
    this.len = len;
    this.angle = angle;
    this.position = new Vector2(x + this.len * cos(this.angle), y + this.len * sin(this.angle));
    this.velocity = new Vector2();
    this.head = new Vector2(
    this.position.x + this.len * cos(this.angle),
    this.position.y + this.len * sin(this.angle));

    this.color = 'hsla(0,0%,0%,0)';
    this.renderProps = {
      line: {
        x1: this.position.x,
        y1: this.position.y,
        x2: this.head.x,
        y2: this.head.y,
        w: 1,
        c: this.color },

      arcLine: {
        x: this.head.x,
        y: this.head.y,
        r: this.jointSize,
        s: 0,
        e: TAU,
        c: this.color } };


  }
  update() {
    this.tick++;
    this.angle = Math.atan2(
    this.parent.position.y - this.position.y,
    this.parent.position.x - this.position..........完整代码请登录后点击上方下载按钮下载查看

网友评论0