svg实现线条绘制三角canvas动画效果代码

代码语言:html

所属分类:动画

代码描述:svg实现线条绘制三角canvas动画效果代码

代码标签: 绘制 三角 canvas 动画 效果

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

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

<head>

 
<meta charset="UTF-8">



 
 
 
 
<style>
document
, body {
 
margin: 0;
 
min-height: 100vh;
}

body
{
 
align-items: center;
 
display: flex;
 
justify-content: center;
}

#container {
 
align-items: center;
 
display: flex;
 
flex-direction: column;
}

#container > :first-child {
 
cursor: pointer;
}

button
{
 
max-width: 200px;
 
margin-top: 10px;
}

canvas
, svg {
 
width: 100vw;
 
height: 100vh;
}
</style>



</head>

<body >
 
<div id="container"></div>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/svg.min.js"></script>
     
<script type="module">

import { Vec2 } from 'https://cdn.skypack.dev/wtc-math';
console.clear();

const config = {
  drawingType: 1,
  dimensions: (new Vec2(window.innerWidth, window.innerHeight)).scale(2),
  breakRun: 2000,
  maxDepth: 12,
  maxPerRun: 100,
  insertType: 1,
  randomType: 0
};
const vars = {
  drawing: null,
  i:0,
  running: true,
  triangles: []
}
const setup = () => {
  vars.running = false;
  setTimeout(() => {
    vars.running = true;
    vars.triangles = [];
    config.insertType = Math.floor(Math.random() * 3);
    config.randomType = Math.floor(Math.random() * 3);
    vars.i=0;
   
    document.querySelector('#container').innerHTML = '';
    vars.drawing = new Drawing(config.drawingType).addTo('#container').size(config.dimensions);
    document.body.querySelector('#container>:first-child').addEventListener('click', () => {
      setup();
    });
   
    draw();
  }, 100);
};

window.addEventListener('resize', () => {
  config.dimensions = ( new Vec2(window.innerWidth, window.innerHeight)).scale(2)
  setup();
});

let depth = 0;
const ts = [
  ['a', 'b'],
  ['b', 'c'],
  ['c', 'a']
];
const drawStep = () => {
  if(!vars.running) return;
  if(vars.i > 2000) return;
  let newTriangles = [];
  vars.triangles.forEach((triangle,i) => {
    if(i>config.breakRun) {
      // newTriangles.splice(0,0,triangle);
      return;
    }
    vars.drawing.polygon(triangle.points);
    let c = triangle.randomCentroid;
    if(config.randomType == 0) {
      c = triangle.centroid;
    }
   
    // vars.drawing.circle(c, 5);
    if(triangle.depth < config.maxDepth) {
      ts.forEach(t => {
        const tr = new Triangle(triangle[t[0]], triangle[t[1]], c);
        tr.depth=triangle.depth+1;
        newTriangles.push(tr);
      });
    }
  });
  if(config.insertType === 0) {
    if(vars.triangles.length>config.breakRun) newTriangles = vars.triangles.splice(config.breakRun).concat(newTriangles);
  } else if(config.insertType === 1) {
    if(vars.triangles.length>config.breakRun) newTriangles = vars.triangles.splice(config.breakRun).reverse().concat(newTriangles);
  } else {
    newTriangles = newTriangles.concat(vars.triangles.splice(config.breakRun));
  }
 
  vars.triangles = newTriangles;
  vars.i++;
  requestAnimationFrame(drawStep);
}
let interval;
const draw = () => {
  vars.drawing.linewidth = 1;
  vars.drawing.fill = "#333";
  vars.drawing.rect(new Vec2(0,0), config.dimensions);
  vars.drawing.linewidth = 1;
  vars.drawing.fill = null;
  vars.drawing.stroke = 'rgba(255,255,255,.02)'
 
  const r = Math.min(config.dimensions.x, config.dimensions.y) * .6;
  const offset = r * 0.2333;
  const points = [];
  for(let i = 0.; i < Math.PI * 2; i += Math.PI * 2. / 3.) {
    points.push( new Vec2(Math.cos(i+Math.PI*.5) * r + config.dimensions.x / 2, Math.sin(i+Math.PI*.5) * r + config.dimensions.y / 2 - offset) );
  }
 
  const t = new Triangle(...points);
 t.depth=0;
  vars.triangles.push(t);
 
  drawStep();
}

class Triangle {
 
  #points
 
  constructor(a, b, c) {
    this.points = [a, b, c];
  }
 
  set points(p) {
    if(p.reduce((a, c) => c instanceof Vec2 ? a+1 : 0, 0) === 3) this.#points = p;
  }
  get points() {
    return this.#points || [];
  }
 
  get a() {
    return this.#points[0];
  }
  get b() {
    return this.#points[1];
  }
  get c() {
    return this.#points[2];
  }
 
  get circumcenter() {
    const d = this.b.subtractNew(this.a);
    const e = this.c.subtractNew(this.a);

    const bl = d.x * d.x + d.y * d.y;
    const cl = e.x * e.x + e.y * e.y;
    const ds = 0.5 / (d.x * e.y - d.y * e.x);
   
    return new Vec2(
      this.a.x + (e.y * bl - d.y * cl) * ds,
      this.a.y + (d.x * cl - e.x * bl) * ds
    );
  }
  get randomCentroid() {
    let a = floatRandomBetween(.2,1.8);
    let b = floatRandomBetween(.2,1.8);
    let c = floatRandomBetween(.2,1.8);
    let abc = a+b+c;
    const f = (3-abc)/3;
    a += f;
    b += f;
    c += f;
    return this.a.scaleNew(a).add(this.b.scaleNew(b)).add(this.c.scaleNew(c)).divideScalar(3);
  }
  get centroid() {
    const a = floatRandomBetween(.5,1.5);
    const b = floatRandomBetween(.5,1.5);
    const c = floatRandomBetween(.5,1.5);
    const abc = a+b+c;
    return this.a.addNew(this.b).add(this.c).divideScalar(3);
  }
 
  get isComplete() {
    return this.points.reduce((a, c) => c instanceof Vec2 ? a+1 : 0, 0) === 3;
  }
 
  get segments() {
    return [
      {
        a: this.a,
        b: this.b,
        c: this.c,
        segment: this.a.subtractNew(this.b)
      },
      {
      .........完整代码请登录后点击上方下载按钮下载查看

网友评论0