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, viewport-fit=cover">
  
  
  
<style>
* {
	border: 0;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
}

body {
	background: hsl(223,10%,90%);
	display: flex;
	height: 100vh;
}
canvas {
	display: block;
	margin: auto;
	object-fit: contain;
	max-width: 100vw;
	max-height: 100vh;
}

/* Dark theme */
@media (prefers-color-scheme: dark) {
	body {
		background: hsl(223,10%,10%);
	}
}
</style>



</head>

<body  >
  <canvas role="img" aria-label="A tree growing until it bears fruit, dropping its fruit, shrinking, and repeating the cycle"></canvas>

      <script  >
window.addEventListener("DOMContentLoaded", () => {
  const t = new Tree("canvas");
});

class Tree {
  constructor(qs) {
    this.C = document.querySelector(qs);
    this.c = this.C?.getContext("2d");
    this.S = window.devicePixelRatio;
    this.W = 800;
    this.H = 800;
    this.branches = [];
    this.darkTheme = false;
    this.debug = false;
    this.decaying = false;
    this.floorY = 685;
    this.fruit = [];
    this.gravity = 0.098;
    this.loopDelay = 500;
    this.loopEnd = Utils.dateValue;
    this.maxGenerations = 10;

    if (this.C) this.init();
  }
  get allBranchesComplete() {
    const { branches, maxGenerations } = this;

    return branches.filter(b => {
      const isLastGen = b.generation === maxGenerations;
      return b.progress >= 1 && isLastGen;
    }).length > 0;
  }
  get allFruitComplete() {
    return !!this.fruit.length && this.fruit.every(f => f.progress === 1);
  }
  get allFruitFalling() {
    return !!this.fruit.length && this.fruit.every(f => f.timeUntilFall <= 0);
  }
  get debugInfo() {
    return [
    { item: 'Pixel Ratio', value: this.S },
    { item: 'Branches', value: this.branches.length },
    { item: 'Branches Complete', value: this.allBranchesComplete },
    { item: 'Decaying', value: this.decaying },
    { item: 'Fruit', value: this.fruit.length },
    { item: 'Fruit Complete', value: this.allFruitComplete }];

  }
  get lastGeneration() {
    const genIntegers = this.branches.map(b => b.generation);
    return [...new Set(genIntegers)].pop();
  }
  get trunk() {
    return {
      angle: 0,
      angleInc: 20,
      decaySpeed: 0.0625,
      diameter: 10,
      distance: 120,
      distanceFade: 0.2,
      generation: 1,
      growthSpeed: 0.04,
      hadBranches: false,
      progress: 0,
      x1: 400,
      y1: 680,
      x2: 400,
      y2: 560 };

  }
  detectTheme(mq) {
    this.darkTheme = mq.matches;
  }
  draw() {
    const { c, W, H, debug, branches, fruit } = this;

    c.clearRect(0, 0, W, H);

    const lightness = this.darkTheme ? 90 : 10;
    const foreground = `hsl(223,10%,${lightness}%)`;
    c.fillStyle = foreground;
    c.strokeStyle = foreground;

    // debug info
    if (debug === true) {
      const textX = 24;

      this.debugInfo.forEach((d, i) => {
        c.fillText(`${d.item}: ${d.value}`, textX, 24 * (i + 1));
      });
    }

    // branches
    branches.forEach(b => {
      c.lineWidth = b.diameter;
      c.beginPath();
      c.moveTo(b.x1, b.y1);
      c.lineTo(
      b.x1 + (b.x2 - b.x1) * b.progress,
      b.y1 + (b.y2 - b.y1) * b.progress);

      c.stroke();
      c.closePath();
    });

    // fruit
    fruit.forEach(f => {
      c.globalAlpha = f.decayTime < f.decayFrames ? f.decayTime / f.decayFrames : 1;
      c.beginPath();
      c.arc(f.x, f.y, f.r * f.progress, 0, 2 * Math.PI);
      c.fill();
      c.closePath();
      c.globalAlpha = 1;
    });
  }
  grow() {
    // start with the trunk
    if (!this.branches.length && Utils.dateValue - this.loopEnd > this.loopDelay) {
      this.branches.push(this.trunk);
    }

    if (!this.allBranchesComplete) {
      this.branches.forEach(b => {
        if (b.progress < 1) {
          // branch growth
          b.progress += b.growthSpeed;

          if (b.progress > 1) {
            b.progress = 1;

            // grow fruit if the generation is the las.........完整代码请登录后点击上方下载按钮下载查看

网友评论0