# proton-engine粒子引擎

# API名词分析

  • Alpha 透明度
  • Attraction 吸引
  • Velocity 速度
  • Collision 碰撞
  • Color 颜色
  • CrossZone 跨区
  • Force 力
  • Gravity 重力
  • GravityWell 重力井
  • Pool 池
  • RandomDrift 随机漂移
  • Repulsion 排斥
  • Rate 比率
  • Scale 缩放

# Alpha

  • API
  new .Alpha(a, b, lifeopt, easingopt)
1
  • 设置粒子的透明度
  emitter.addBehaviour(new Proton.Alpha(1,0,Infinity,  Proton.easeOutQuart))
1

# Attraction

  • API
  new .Attraction(targetPosition, forceopt, radiusopt, lifeopt, easingopt)
1
  • 生成引力厂
  emitter.addBehaviour(
    new Proton.Attraction(
      new Proton.Vector2D(window.innerWidth / 2, window.innerHeight / 2),
      1000, 
      10000, 
      Infinity,
      Proton.easeLinear
    )
  )
1
2
3
4
5
6
7
8
9

# Collision

  • API
  new .Collision(emitteropt, massopt, callbackopt, lifeopt, easingopt)
1
  • 用法
// eg:
 emitter.addBehaviour(new Proton.Collision(emitter));
1
2

# Color

  • API
  new .Color(color1, color2, lifeopt, easingopt)
1
  • 设置粒子颜色
   emitter.addBehaviour(new Proton.Color(
      'random', // 随机颜色
      '#cccccc55', // rgb颜色值
      Infinity,
      Proton.easeOutQuart
    )
  )
1
2
3
4
5
6
7

# CrossZone

  • API
  new .CrossZone(zone, crossTypeopt, lifeopt, easingopt)
1
  • 用法
  emitter.addBehaviour(new Proton.CrossZone(
      //  定义区域形状 
      new Proton.RectZone(0,0,window.innerWidth,window.innerHeight),
      'bound', // strings: dead | bound | cross
      Infinity,
      Proton.easeLinear
    )
  )
1
2
3
4
5
6
7
8

# Force

  • API
  new .Force(fx, fy, lifeopt, easingopt)
1
  • 给X,Y轴增加力,粒子就会沿着力的方向进行运动
  //  eg:给一个X轴正方向和Y轴父方向的力,粒子就会向右上角运动  
  emitter.addBehaviour(new Proton.Force(10,-10,Infinity,Proton.easeOutQuart))
1
2

# Gravity

  • API
  new .Gravity(g, lifeopt, easingopt)
1
  • 用法
  // 第一个参数g,填写正数:向下, 负数:向上,0:保持原粒子状态
  emitter.addBehaviour(new Proton.Gravity(0,Infinity,Proton.easeLinear))
1
2

# GravityWell

  • API
  new .GravityWell(centerPointopt, forceopt, lifeopt, easingopt)
1
  • 可以用来模拟黑洞
  emitter.addBehaviour(new Proton.GravityWell(
      new Proton.Vector2D(window.innerWidth/2,window.innerHeight/2),
      1000, // 引力大小
      Infinity, // 生命周期
      Proton.easeLinear
    )
  )
1
2
3
4
5
6
7

# Pool

  • 用法,这个API目前还没有完全理解,但是可以这样试一下,缓存已经发射的粒子
let pool = new Proton.Pool(context)
    pool.cache.once = emitter.particles
    console.log(pool)
    // {
    //   cache:{
    //     xxx:{xxxx}
    //   },
    //   total:xxx
    // }
1
2
3
4
5
6
7
8
9

# RandomDrift

  • API
  new .RandomDrift(driftX, driftY, delay, lifeopt, easingopt)
1
  • 在粒子移动中随机给粒子施加x轴或者y轴的力
  emitter.addBehaviour(new Proton.RandomDrift(
        30, // 在x轴施加力
        10, // 在y轴施加力
        0.05, // 漂移延迟时间
        2,
        Proton.easeOutQuart
      )
    )
1
2
3
4
5
6
7
8

# Rate

  • API
  new .Rate(numpan, timepan)
1
  • 粒子的发射比率
  emitter.rate = new Proton.Rate(
    Proton.getSpan(1, 90), // 每次发射1~90个之间的粒子数
    Proton.getSpan(1, 10) // 每隔1~10秒发射一次粒子
  )
1
2
3
4

# Repulsion

  • API
  new .Repulsion(targetPosition, forceopt, radiusopt, lifeopt, easingopt)
1
  • 不同于GravityWell的引力,这个是排斥力,粒子会被排斥走
  emitter.addBehaviour(new Proton.Repulsion(
      new Proton.Vector2D(window.innerWidth/2,window.innerHeight/2),
      100, // 排斥里
      100, // 排斥半径
      Infinity,
      Proton.easeLinear
    )
  )
1
2
3
4
5
6
7
8

# Scale

  • API
 new .Scale(a, b, lifeopt, easingopt)
1
  • 设置粒子的缩放
// 粒子开始渲染时候是五倍的大小,随着生命周期而变小,变为原大小
emitter.addBehaviour(new Proton.Scale(5,0,Infinity,  Proton.easeOutQuart))
1
2

# 加载图片

  • 用法
  // import source -- use react demo
  import star from './assets/img/star.png'

  // 使用引入的图片给粒子进行初始化
  emitter.addInitialize(new Proton.Body(star))
1
2
3
4
5

# 生成烟花

  • 用react举例,这里默认先用create-react-app初始化了一个react项目
  • 需要安装的插件
  yarn add raf-manager proton-engine
1
  • 先准备HTML部分
  // ...
  return (
    <div className="container">
      <canvas ref={canvasEL} onClick={particle} className="main-bg"></canvas>
    </div>
  );
}
export default App;
1
2
3
4
5
6
7
8
  • 引入该引入的包
import React, { useEffect, useRef } from 'react';
import Proton from 'proton-engine'
import RAF from 'raf-manager'
1
2
3
  • 初始化全局变量
  const proton = new Proton() // 初始化粒子引擎实例
  const emitter = new Proton.Emitter() // 定义emitter实例
  let canvasEL = useRef('') // 获取canvas标签
  let context = null // 初始化canvas的上下文
1
2
3
4
  • 在组件加载的时候执行的代码 core
  useEffect(() => {
    canvasInit() // 初始化canvas
    canvasResize() // canvas 根据window大小改变而改变
    particleAnimation()
  })

  function canvasInit () {
    canvasEL.current.width = window.innerWidth
    canvasEL.current.height = window.innerHeight
    context = canvasEL.current.getContext('2d')
  }

  function canvasResize () {
    window.onresize = function (e) {
      canvasEL.current.width = window.innerWidth
      canvasEL.current.height = window.innerHeight
      emitter.p.x = canvasEL.current.width / 2
      emitter.p.y = canvasEL.current.height / 2
    }
  }

  function particleAnimation() {
    //set Rate
    emitter.rate = new Proton.Rate(Proton.getSpan(20, 40))
    //add Initialize
    emitter.addInitialize(new Proton.Radius(0.5, 3))
    emitter.addInitialize(new Proton.Life(10))
    emitter.addInitialize(new Proton.Mass(1))
    emitter.addInitialize(new Proton.Velocity(new Proton.Span(1, 2),
      new Proton.Span(0, 360), 'polar'))
    let forceBehaviour = new Proton.Force(0, 0);
    emitter.addBehaviour(forceBehaviour, new Proton.Gravity(.9))
    emitter.addBehaviour(new Proton.Color('random', 'random', '#cccccc55', Infinity, Proton.easeOutQuart))
    emitter.addBehaviour(new Proton.Alpha(1, 0, Infinity, Proton.easeOutQuart))
    emitter.addBehaviour(new Proton.Scale(5, 0, Infinity, Proton.easeOutQuart))
    //set emitter position
    emitter.p.x = canvasEL.current.width / 2;
    emitter.p.y = canvasEL.current.height / 2;
    emitter.emit('once')
    //add emitter to the proton
    proton.addEmitter(emitter)
    // add canvas renderer
    const renderer = new Proton.CanvasRenderer(canvasEL.current)
    renderer.onProtonUpdate = () => {
      context.fillStyle = "rgba(0, 0, 0, 0.1)";
      context.fillRect(0, 0, canvasEL.current.width, canvasEL.current.height);
    }
    proton.addRenderer(renderer)
    // 用来执行proton的更新渲染方法
    RAF.add(() => {
      proton.update()
    }, 1000)
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  • 最后注册点击事件,绑定在canvas上
  const particle = (event) => {
    emitter.p.x = event.clientX // 指定粒子发射x轴位置
    emitter.p.y = event.clientY // 指定粒子发射y轴位置
    emitter.emit('once') // 粒子发射一次
    event.persist()
  }
1
2
3
4
5
6
Last Updated: 1/23/2022, 10:16:22 AM