<template>
  <div class="canvas-wrap">
    <canvas id="lineCanvas" width="300" height="300"></canvas>
    <canvas id="carCanvas" width="300" height="300"></canvas>
  </div>
</template>

<script>
import Easing from '@config/Easing.js'
export default {
  data () {
    return {
      keyPoints: [{x: 160, y: 200}, {x: 60, y: 200}, {x: 60, y: 400}, {x: 160, y: 400}]
    }
  },
  mounted () {
    setTimeout(() => {
      this.handleCanvasLine()
    }, 5000)
    setTimeout(() => {
      this.handleCanvasCar()
    }, 5900)
  },
  methods: {
    handleCanvasLine () {
      const canvas = document.querySelector('#lineCanvas')
      const ctx = canvas.getContext('2d')
      let img = new Image()
      img.src = require('../images/che.png')
      // 设置线条样式
      ctx.lineWidth = 1
      ctx.lineJoin = 'round'
      ctx.lineCap = 'round'
      let prevX = this.keyPoints[0].x
      let prevY = this.keyPoints[0].y
      let nextX
      let nextY
      // 第一帧执行的时间
      let startTime
      // 期望动画持续的时间
      const duration = 900
      // 动画被切分成若干段,每一段所占总进度的比例
      const partProportion = 1 / (this.keyPoints.length - 1)
      // 缓存绘制第n段线段的n值,为了在进行下一段绘制前把这一段线段的末尾补齐
      let lineIndexCache = 1
      // 动画帧绘制方法currentTime是requestAnimation执行回调方法step时会传入的一个执行时的时间(由performance.now()获得).
      const step = (currentTime) => {
        // 第一帧绘制时记录下开始的时间
        !startTime && (startTime = currentTime)
        // 已经过去的时间(ms)
        const timeElapsed = currentTime - startTime
        // 动画执行的进度 {0,1}
        let progress = Math.min(timeElapsed / duration, 1)
        // 加入二次方缓动函数
        progress = Easing.Quadratic.In(progress)
        // 描述当前所绘制的是第几段线段
        const lineIndex = Math.min(Math.floor(progress / partProportion) + 1, this.keyPoints.length - 1)
        //  当前线段的进度 {0,1}
        const partProgress = (progress - (lineIndex - 1) * partProportion) / partProportion
        // 绘制方法
        const draw = () => {
          ctx.strokeStyle = `rgba(${81 + 175 * Math.abs(1 - progress * 2)}, ${160 - 160 * Math.abs(progress * 2 - 1)}, ${255},${1})`
          ctx.beginPath()
          ctx.moveTo(prevX, prevY)
          // 当绘制下一段线段前,把上一段末尾缺失的部分补齐
          if (lineIndex !== lineIndexCache) {
            ctx.lineTo(this.keyPoints[lineIndex - 1].x, this.keyPoints[lineIndex - 1].y)
            lineIndexCache = lineIndex
          }
          prevX = nextX = ~~(this.keyPoints[lineIndex - 1].x + ((this.keyPoints[lineIndex]).x - this.keyPoints[lineIndex - 1].x) * partProgress)
          prevY = nextY = ~~(this.keyPoints[lineIndex - 1].y + ((this.keyPoints[lineIndex]).y - this.keyPoints[lineIndex - 1].y) * partProgress)
          ctx.lineTo(nextX, nextY)
          ctx.stroke()
        }
        draw()
        if (progress < 1) {
          requestAnimationFrame(step)
        } else {
          console.log('动画执行完毕')
        }
      }
      requestAnimationFrame(step)
    },
    handleCanvasCar () {
      const canvas = document.querySelector('#carCanvas')
      const ctx = canvas.getContext('2d')
      let img = new Image()
      img.src = require('../images/che.png')
      let nextX
      let nextY
      // 第一帧执行的时间
      let startTime
      // 期望动画持续的时间
      const duration = 2000
      // 动画被切分成若干段,每一段所占总进度的比例
      const partProportion = 1 / (this.keyPoints.length - 1)
      // 缓存绘制第n段线段的n值,为了在进行下一段绘制前把这一段线段的末尾补齐
      // 动画帧绘制方法currentTime是requestAnimation执行回调方法step时会传入的一个执行时的时间(由performance.now()获得).
      const step = (currentTime) => {
        // 第一帧绘制时记录下开始的时间
        !startTime && (startTime = currentTime)
        // 已经过去的时间(ms)
        const timeElapsed = currentTime - startTime
        // 动画执行的进度 {0,1}
        let progress = Math.min(timeElapsed / duration, 1)
        // 加入二次方缓动函数
        progress = Easing.Quadratic.In(progress)
        // 描述当前所绘制的是第几段线段
        const lineIndex = Math.min(Math.floor(progress / partProportion) + 1, this.keyPoints.length - 1)
        //  当前线段的进度 {0,1}
        const partProgress = (progress - (lineIndex - 1) * partProportion) / partProportion
        // 绘制方法
        const draw = () => {
          ctx.beginPath()
          ctx.clearRect(0, 0, 400, 500)
          nextX = ~~(this.keyPoints[lineIndex - 1].x + ((this.keyPoints[lineIndex]).x - this.keyPoints[lineIndex - 1].x) * partProgress)
          nextY = ~~(this.keyPoints[lineIndex - 1].y + ((this.keyPoints[lineIndex]).y - this.keyPoints[lineIndex - 1].y) * partProgress)
          ctx.drawImage(img, nextX - 15, nextY - 50, 30, 50)
        }
        draw()
        if (progress < 1) {
          requestAnimationFrame(step)
        } else {
          console.log('动画执行完毕')
        }
      }
      requestAnimationFrame(step)
    }
  }
}
</script>

<style lang="stylus" scoped>
.canvas-wrap
  position relative
  width 100%
  height 100%
#lineCanvas
  position absolute
  left 0
  top 0
  z-index 10
#carCanvas
  position absolute
  left 0
  top 0
  z-index 11
</style>
