Skip to content

Latest commit

 

History

History
165 lines (146 loc) · 4.34 KB

File metadata and controls

165 lines (146 loc) · 4.34 KB
落彩条动画效果
/**
 * 落彩条动画效果
 */
export default class Animation {
  constructor () {
    this.animation = null
    this.colors = [
      '#26ccff',
      '#a25afd',
      '#ff5e7e',
      '#88ff5a',
      '#fcff42',
      '#ffa62d',
      '#ff36ff'
    ]
    this.arr = []
    this.initEle()
    this.canvas = this.initCanvas(999)
    document.body.appendChild(this.canvas)
    this.context = this.canvas.getContext('2d')
  }

  initElement () {
    let TIME = Math.floor(1000 / 60)
    let frame, cancel
    let frames = {}
    let lastFrameTime = 0
    let _this = this
    if (typeof requestAnimationFrame === 'function' && typeof cancelAnimationFrame === 'function') {
      frame = function (cb) {
        let id = Math.random()
        frames[id] = requestAnimationFrame(function onFrame (time) {
          if (lastFrameTime === time || lastFrameTime + TIME - 1 < time) {
            lastFrameTime = time
            delete frames[id]
            cb(_this)
          } else {
            frames[id] = requestAnimationFrame(onFrame)
          }
        })
        return id
      }
      cancel = function (id) {
        if (frames[id]) {
          cancelAnimationFrame(frames[id])
        }
      }
    } else {
      frame = function (cb) {
        return setTimeout(cb, TIME)
      }
      cancel = function (timer) {
        return clearTimeout(timer)
      }
    }

    return {frame: frame, cancel: cancel}
  }

  initCanvas (zIndex) {
    let canvas = document.createElement('canvas')
    canvas.width = document.documentElement.clientWidth
    canvas.height = document.documentElement.clientHeight
    canvas.style.cssText = `position: fixed; top: 0px; left: 0px; pointer-events: none; z-index: ${zIndex};`

    setTimeout(() => {
      document.body.removeChild(canvas)
    }, 1000)

    return canvas
  }

  hexToRgb (str) {
    var val = String(str).replace(/[^0-9a-f]/gi, '')

    if (val.length < 6) {
      val = val[0] + val[0] + val[1] + val[1] + val[2] + val[2]
    }

    return {
      r: parseInt(val.substring(0, 2), 16),
      g: parseInt(val.substring(2, 4), 16),
      b: parseInt(val.substring(4, 6), 16)
    }
  }

  updateElement (context, element) {
    let progress = (element.tick++) / element.totalTicks
    if (progress > 1) return
    element.x += Math.cos(element.angle2D) * element.velocity // 左下角
    element.y += Math.sin(element.angle2D) * element.velocity + element.gravity // 左下角

    element.velocity *= element.decay
    element.tiltAngle += 0.1
    element.tiltSin = Math.sin(element.tiltAngle)
    element.tiltCos = Math.cos(element.tiltAngle)
    element.random = Math.random() + 7

    let x1 = element.x
    let y1 = element.y

    let x2 = element.x + (element.random * element.tiltCos) // 左上角
    let y2 = element.y + (element.random * element.tiltSin) // 左上角

    let x3 = x2 + element.random
    let y3 = y2

    let x4 = element.x + element.random
    let y4 = element.y

    context.fillStyle = `rgba(${element.color.r},${element.color.g},${element.color.b},${(1 - progress)})`
    context.beginPath()
    context.moveTo(Math.floor(x1), Math.floor(y1))
    context.lineTo(Math.floor(x2), Math.floor(y2))
    context.lineTo(Math.floor(x3), Math.floor(y3))
    context.lineTo(Math.floor(x4), Math.floor(y4))
    context.closePath()
    context.fill()

    return element.tick < element.totalTicks
  }

  update (_this) {
    _this.context.clearRect(0, 0, _this.canvas.width, _this.canvas.height)
    _this.arr = _this.arr.filter(item => {
      return _this.updateElement(_this.context, item)
    })
    if (_this.arr.length) {
      _this.animation = _this.initElement().frame(_this.update)
    }
  }

  initEle () {
    for (let i = 0; i < 100; i++) {
      this.arr.push({
        "x": 0,
        "y": 600,
        "velocity": (45 * 0.5) + (Math.random() * 20),
        "angle2D": 3 / 2 * Math.PI + Math.random() * 1 / 4 * Math.PI,
        "tiltAngle": Math.random() * Math.PI,
        "color": this.hexToRgb(this.colors[Math.floor(Math.random() * 7)]),
        "tick": 0,
        "totalTicks": 350,
        "decay": 0.95,
        "random": 0,
        "tiltSin": 0,
        "tiltCos": 0,
        "gravity": 3,
        "scalar": 1
      })
    }
  }

  // 动画生成方法
  giftRun () {
    if (!this.animation) {
      this.animation = this.initElement().frame(this.update)
    } else {
      this.initEle()
    }
  }
}