canvas实现可调节参数的线条动画效果代码

代码语言:html

所属分类:动画

代码描述:canvas实现可调节参数的线条动画效果代码,可调节线条数量方向、颜色、初始数量、中间大小、尾部大小、发射半径、坐标等参数。

代码标签: canvas 调节 参数 线条 动画

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

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

<head>


    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Anime Speedlines Demo</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            background-color: #1a1a1a;
            color: white;
            font-family: Arial, sans-serif;
            overflow: hidden;
        }
        #speedlineCanvas {
            position: fixed;
            top: 0;
            left: 0;
        }
        #controls {
            position: fixed;
            top: 10px;
            left: 10px;
            background-color: rgba(0, 0, 0, 0.7);
            padding: 10px;
            border-radius: 5px;
            max-height: 90vh;
            overflow-y: auto;
        }
        #controls label {
            display: block;
            margin-top: 5px;
        }
        #currentSettings {
            position: fixed;
            bottom: 10px;
            left: 10px;
            background-color: rgba(0, 0, 0, 0.7);
            padding: 10px;
            border-radius: 5px;
            font-family: monospace;
            white-space: pre-wrap;
        }
input {
    display: flex;
      }
    </style>
</head>
<body>
    <canvas id="speedlineCanvas"></canvas>
    <div id="controls">
        <h2>Speedline Controls</h2>
        <label>
            Type:
            <select id="type">
                <option value="linear">Linear</option>
                <option value="radial">Radial</option>
            </select>
        </label>
        <label>
            Count: <input type="number" id="count" value="100" onInput="updateSettings();">
        </label>
        <label>
            Speed: <input type="number" id="speed" value="5">
        </label>
        <label>
            Length: <input type="number" id="length" value="500">
        </label>
        <label>
            Color: <input type="color" id="color" value="#ffffff">
        </label>
        <label>
            Initial Size: <input type="number" id="initialSize" value="1">
        </label>
      <label>
            Middle Size: <input type="number" id="middleSize" value="1">
        </label>
        <label>
            End Size: <input type="number" id="endSize" value="5">
        </label>
        <label>
            Emitter Radius: <input type="number" id="emitterRadius" value="250">
        </label>
        <label>
            angle: <input type="number" id="angle" value="45" min="0" max="360">
        </label>
        <label>
            Emitter X: <input type="number" id="emitterX" value="50" min="0" max="100" step="1">
        </label>
        <label>
            Emitter Y: <input type="number" id="emitterY" value="50" min="0" max="100" step="1">
        </label>
    </div>
    <div id="currentSettings"></div>


      <script  >
// Utility functions
const randomFactor = () => 0.5 + Math.random() * 0.5;
const radToDeg = rad => rad * 180 / Math.PI;
const degToRad = deg => deg * Math.PI / 180;

class Vector2 {
  constructor(x = 0, y = 0) {
    this.x = x;
    this.y = y;
  }

  static fromAngle(angle, length = 1) {
    return new Vector2(Math.cos(angle) * length, Math.sin(angle) * length);
  }

  add(v) {
    this.x += v.x;
    this.y += v.y;
    return this;
  }

  sub(v) {
    this.x -= v.x;
    this.y -= v.y;
    return this;
  }

  mult(n) {
    this.x *= n;
    this.y *= n;
    return this;
  }

  div(n) {
    this.x /= n;
    this.y /= n;
    return this;
  }

  mag() {
    return Math.sqrt(this.x * this.x + this.y * this.y);
  }

  normalize() {
    const m = this.mag();
    if (m !== 0) this.div(m);
    return this;
  }

  setMag(len) {
    return this.normalize().mult(len);
  }

  copy() {
    return new Vector2(this.x, this.y);
  }}


class Line {
  constructor(canvas, settings, isInitial = false) {
    this.canvas = canvas;
    this.settings = settings;
    this.pos = new Vector2();
    this.vel = new Vector2();
    this.initialize(isInitial);
  }

  initialize(isInitial = false) {
    const { type, angle, emitterRadius, emitterX, emitterY, speed, length } = this.settings;
    const emitterPos = new Vector2(this.canvas.width * (emitterX / 100), this.canvas.height * (emitterY / 100));

    this.randomizedEmitterRadius = emitterRadius * randomFactor();
    this.speed = speed * randomFactor();
    this.length = length * randomFactor();

    const angleRad = type === 'radial' ? Math.random() * Math.PI * 2 : degToRad(angle);

    if (type === 'radial') {
      const maxDistance = Math.max(this.canvas.width, this.canvas.height);
      const initialDistance = isInitial ? Math.random() : this.speed >= 0 ? 0 : 1;
      const r = this.randomizedEmitterRadius + initialDistance * maxDistance;
      this.pos = Vector2.fromAngle(angleRad, r).add(emitterPos);
      this.vel = Vector2.fromAngle(angleRad, Math.abs(this.speed));
    } else {
      this.pos = new Vector2(Math.random() * this.canvas.width, Math.random() * this.canvas.height);
      this.vel = Vector2.fromAngle(angleRad, this.speed);
    }

    this.sizes = ['initialSize', 'middleSize', 'endSize'].map(size => this.settings[size] * randomFactor());
  }

  update() {
    const { type, emitterX, emitterY } = this.settings;
    const emitterPos = new Vector2(this.canvas.width * (emitterX / 100), this.canvas.height * (emitterY / 100));

    if (type.........完整代码请登录后点击上方下载按钮下载查看

网友评论0