pixi+victor实现跟随鼠标彩虹发光烟花粒子动画效果代码

代码语言:html

所属分类:粒子

代码描述:pixi+victor实现跟随鼠标彩虹发光烟花粒子动画效果代码

代码标签: pixi victor 跟随 鼠标 彩虹 发光 烟花 粒子 动画

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

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

<head>
  <meta charset="UTF-8">
  

  
  
<style>
html, body {
  padding: 0;
  margin: 0;
  overflow: hidden;
}
</style>

  
</head>

<body>
<script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/pixi.7.2.4.js"></script>
  <script type="text/javascript" src="//repo.bfw.wiki/bfwrepo/js/victor.1.1.0.js"></script>
      <script type="module">

console.clear();

const SHOW_FLOW_FIELD = false;
const PARTICLE_COUNT = 30000;
const GRID_RESOLUTION = 30;

function hslToHex(h, s, l) {
  l /= 100;
  const a = s * Math.min(l, 1 - l) / 100;
  const f = n => {
    const k = (n + h / 30) % 12;
    const color = l - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
    return Math.round(255 * color).toString(16).padStart(2, '0');   // convert to Hex and prefix "0" if needed
  };
  return `#${f(0)}${f(8)}${f(4)}`;
}

class Walker {
  constructor (texture, size, radius) {
    this.radius = radius
    this.size = size;
    this.speed = 0;
    this.startSpeed = 10;
    this.hue = 0;
    this.sparkleCount = 1;
    this.vectorWeight = 1;
    
    this.sprite = new PIXI.Sprite(texture);
    this.sprite.anchor.set(0.5);
    this.vector = new Victor( Math.random() * 2 - 1, Math.random() * 2 - 1)
    
    this.sprite.x = (this.size.x * 0.5) * (this.size.grid + this.size.gutter)
    this.sprite.y = (this.size.y * 0.5) * (this.size.grid + this.size.gutter)
    this.sprite.scale.set(0)
  }
  
  reset(position, direction, distance, hue, explode) {
    this.hue = hue
    this.startSpeed = Math.max(3, Math.min(explode ? 15 : 10, distance))
    this.vector = direction
    this.sparkleCount = 0.2;
    this.speed = this.startSpeed * (explode ? 0.7 + Math.random() * 0.3 : Math.random() * 1);
    this.sprite.x = position.x;
    this.sprite.y = position.y;
    if(explode) this.vectorWeight = 0;
    
  }
  
  move(gridVector, delta) {
    
    this.vectorWeight += 0.05 * delta;
    if(this.vectorWeight > 1) this.vectorWeight = 1;
    this.speed -= 0.06 * delta ;
    if(this.speed <= 0.06) this.speed = 0
    
    this.vector.mix(gridVector, 0.7 * this.vectorWeight).normalize()
    
    let newX = this.sprite.x + this.vector.x * this.speed;
    let newY = this.sprite.y + this.vector.y * this.speed;
    
    const TL = new Victor(this.radius, this.radius);
    const BR = new Victor(
      this.size.x * (this.size.grid + this.size.gutter) - this.radius,
      this.size.y * (this.size.grid + this.size.gutter) - this.radius
    )
    
    if(newX < TL.x || newX > BR.x ) this.vector.invertX();
    if(newY < TL.y || newY > BR.y ) this.vector.invertY();
    
    if(newX < TL.x) this.sprite.x = TL.x;
    if(newX > BR.x) this.sprite.x = BR.x;
    
    if(newY < TL.y) this.sprite.y = TL.y;
    if(newY > BR.y) this.sprite.y = BR.y;
    
    this.sprite.x += (this.vector.x * delta) * this.speed;
    this.sprite.y += (this.vector.y * delta) * this.speed;
    
   
    if(this.speed > 4 && Math.random() > 0.99) this.sparkleCount = 1;
    this.sparkleCount -= 0.1;
    if(this.sparkleCount < 0) this.sparkleCount = 0;
    
    const sparkling = this.sparkleCount > 0 && this.speed > 0.1
    
    this.sprite.scale.set(sparkling ? 1 : this.speed / this.startSpeed)
    this.sprite.tint = hslToHex(this.hue, 100, 50 + ( sparkling ? 50 : 0))
    
  }
  
  clampX (x) {
    return Math.max(0, Math.min(this.size.x - 1, Math.round(x)))
  }
  
  clampY (y) {
    return Math.max(0, Math.min(this.size.y - 1, Math.round(y)))
  }
  
  get x () { return this.clampX(this.sprite.x / (this.size.grid + this.size.gutter))  }
  get y () { return this.clampY(this.sprite.y / (this.size.grid + this.size.gutter))  }
}

class App {
  constructor() {
    this.pixi = new PIXI.Application({ background: '#1c1c1c', resizeTo: window });
    document.body.appendChild(this.pixi.view);
    
    this.size = {
      grid: GRID_RESOLUTION,
      gutter: 1,
      border: 0,
      x: 0,
      y: 0
    }
    
    this.hueCount = 0;
    
    this.walkers = [];
    this.walkerTotal = PARTICLE_COUNT;
    this.walkerCount = 0;
    this.interacted = false;
    this.cursorPoints = []
    this.cursorPosition = new Victor(0, 0);
    this.cursorDirection = new Victor(0, 0);
       
    let arrowGraphic = new PIXI.Graphics()
    
    arrowGraphic.lineStyle(0);
    arrowGraphic.beginFill(0xffffff, 1);
    arrowGraphic.drawPolygon([
      this.size.grid * 0.6, this.size.grid * 0.35, 
      this.size.grid * 0.8, this.size.grid * 0.5,
      this.size.grid * 0.6, this.size.grid * 0.65, 
    ])
    arrowGraphic.drawRect(this.size.grid * 0.1, this.size.grid * 0.5 - 0.5,  this.size.grid * 0.5, 1);
    arrowGraphic.endFill();
    
    this.arrowTexture = this.pixi.renderer.generateTexture(arrowGraphic);
    
    this.points = 0;
    this.grid = null;
    this.arrows = [];
    
    this.container = new PIXI.Container();
    this.pixi.stage.addChild(this.container);
    
    this.pixi.renderer.on('resize', () => this.onResize())
    this.pixi.stage.interactive = true;
    this.pixi.stage.hitArea = this.pixi.screen;

    this.pixi.stage.on("pointermove", (e) => {
      this.interacted = true;
      const pos = e.data.global;
      const newPositionVector =  new Victor(pos.x - Math.max(0, this.size.border * 2), pos.y - Math.max(0, this.size.border * 2))
      
      // this.cursorMoved = true;
      const distance = newPositionVector.distance(this.cursorPosition)
      const newDirectionVector = newPositionVector.clone().subtract(this.cursorPosition)
      this.cursorPosition.copy(newPositionVector)
      this.cursorDirection.mix(newDirectionVector, 0.9)
      
      this.cursorPoints.push({
        position: this.cursorPosition.clone(),
        direction: this.cursorDirection.clone(),
        distance
      })
    });
    
    this.pixi.stage.on("click", (e) => {
      // console.log(e.data.global)
      const pos = e.data.global;
      for(let i = 0; i < 10; i++) {
        this.cursorPoints.push({
          position: new Victor(pos.x, pos.y),
          direction: new Victor(Math.random() * 2 -1, Math.random() * 2 -1),
          distance: 30,
          explode: true
        })
      }
    })
    
    this.onResize()
    
    this.pixi.ticker.add((delta) => this.tick(delta));
    
  }
  
  setFlowField() {
    for(let i = 0; i < this.points * 2; i += 2) {      
      this.grid[i] = Math.sin(i * 0.1); //Math.random() * 2 - 1
      this.grid[i+1] =  Math.sin((i+1) * 0.05);  //Math.rando.........完整代码请登录后点击上方下载按钮下载查看

网友评论0