animation.js 2.8 KB
Newer Older
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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
function converPx (value) {
  if (/\d+[ur]px$/i.test(value)) {
    value.replace(/\d+[ur]px$/i, text => {
      return `${uni.upx2px(parseFloat(text))}px`
    })
    // eslint-disable-next-line no-useless-escape
  } else if (/^-?[\d\.]+$/.test(value)) {
    return `${value}px`
  }
  return value || ''
}

function converType (type) {
  return type.replace(/[A-Z]/g, text => {
    return `-${text.toLowerCase()}`
  }).replace('webkit', '-webkit')
}

function getStyle (action) {
  const animateTypes1 = ['matrix', 'matrix3d', 'scale', 'scale3d', 'rotate3d', 'skew', 'translate', 'translate3d']
  const animateTypes2 = ['scaleX', 'scaleY', 'scaleZ', 'rotate', 'rotateX', 'rotateY', 'rotateZ', 'skewX', 'skewY', 'translateX', 'translateY', 'translateZ']
  const animateTypes3 = ['opacity', 'backgroundColor']
  const animateTypes4 = ['width', 'height', 'left', 'right', 'top', 'bottom']
  const animates = action.animates
  const option = action.option
  const transition = option.transition
  const style = {}
  let transform = []
  animates.forEach(animate => {
    const type = animate.type
    let args = [...animate.args]
    if (animateTypes1.concat(animateTypes2).includes(type)) {
      if (type.startsWith('rotate') || type.startsWith('skew')) {
        args = args.map(value => parseFloat(value) + 'deg')
      } else if (type.startsWith('translate')) {
        args = args.map(converPx)
      }
      if (animateTypes2.indexOf(type)) {
        args.length = 1
      }
      transform.push(`${type}(${args.join(',')})`)
    } else if (animateTypes3.concat(animateTypes4).includes(type)) {
      const value = args[0]
      style[type] = animateTypes4.includes(type) ? converPx(value) : value
    }
  })
  style.transform = style.webkitTransform = transform.join(' ')
  style.transition = style.webkitTransition = Object.keys(style).map(type => `${converType(type)} ${transition.duration}ms ${transition.timingFunction} ${transition.delay}ms`).join(',')
  style.transformOrigin = style.webkitTransformOrigin = option.transformOrigin
  return style
}

function startAnimation (context) {
  const animation = context.animation
  if (!animation || !animation.actions || !animation.actions.length) {
    return
  }
  let index = 0
  const actions = animation.actions
  const length = animation.actions.length
  function animate () {
    const action = actions[index]
    const transition = action.option.transition
    const style = getStyle(action)
    Object.keys(style).forEach(key => {
      context.$el.style[key] = style[key]
    })

    index += 1
    if (index < length) {
      setTimeout(animate, transition.duration + transition.delay)
    }
  }

  animate()
}

export default {
  props: ['animation'],
  watch: {
    animation () {
      startAnimation(this)
    }
  },
  mounted () {
    startAnimation(this)
  }
}