createAnimation.js 3.2 KB
// const defaultOption = {
// 	duration: 300,
// 	timingFunction: 'linear',
// 	delay: 0,
// 	transformOrigin: '50% 50% 0'
// }
// #ifdef APP-NVUE
const nvueAnimation = uni.requireNativePlugin('animation')
// #endif
class MPAnimation {
	constructor(options, _this) {
		this.options = options
		// 在iOS10+QQ小程序平台下,传给原生的对象一定是个普通对象而不是Proxy对象,否则会报parameter should be Object instead of ProxyObject的错误
		this.animation = uni.createAnimation({
			...options
		})
		this.currentStepAnimates = {}
		this.next = 0
		this.$ = _this

	}

	_nvuePushAnimates(type, args) {
		let aniObj = this.currentStepAnimates[this.next]
		let styles = {}
		if (!aniObj) {
			styles = {
				styles: {},
				config: {}
			}
		} else {
			styles = aniObj
		}
		if (animateTypes1.includes(type)) {
			if (!styles.styles.transform) {
				styles.styles.transform = ''
			}
			let unit = ''
			if(type === 'rotate'){
				unit = 'deg'
			}
			styles.styles.transform += `${type}(${args+unit}) `
		} else {
			styles.styles[type] = `${args}`
		}
		this.currentStepAnimates[this.next] = styles
	}
	_animateRun(styles = {}, config = {}) {
		let ref = this.$.$refs['ani'].ref
		if (!ref) return
		return new Promise((resolve, reject) => {
			nvueAnimation.transition(ref, {
				styles,
				...config
			}, res => {
				resolve()
			})
		})
	}

	_nvueNextAnimate(animates, step = 0, fn) {
		let obj = animates[step]
		if (obj) {
			let {
				styles,
				config
			} = obj
			this._animateRun(styles, config).then(() => {
				step += 1
				this._nvueNextAnimate(animates, step, fn)
			})
		} else {
			this.currentStepAnimates = {}
			typeof fn === 'function' && fn()
			this.isEnd = true
		}
	}

	step(config = {}) {
		// #ifndef APP-NVUE
		this.animation.step(config)
		// #endif
		// #ifdef APP-NVUE
		this.currentStepAnimates[this.next].config = Object.assign({}, this.options, config)
		this.currentStepAnimates[this.next].styles.transformOrigin = this.currentStepAnimates[this.next].config.transformOrigin
		this.next++
		// #endif
		return this
	}

	run(fn) {
		// #ifndef APP-NVUE
		this.$.animationData = this.animation.export()
		this.$.timer = setTimeout(() => {
			typeof fn === 'function' && fn()
		}, this.$.durationTime)
		// #endif
		// #ifdef APP-NVUE
		this.isEnd = false
		let ref = this.$.$refs['ani'] && this.$.$refs['ani'].ref
		if(!ref) return
		this._nvueNextAnimate(this.currentStepAnimates, 0, fn)
		this.next = 0
		// #endif
	}
}


const animateTypes1 = ['matrix', 'matrix3d', 'rotate', 'rotate3d', 'rotateX', 'rotateY', 'rotateZ', 'scale', 'scale3d',
	'scaleX', 'scaleY', 'scaleZ', 'skew', 'skewX', 'skewY', 'translate', 'translate3d', 'translateX', 'translateY',
	'translateZ'
]
const animateTypes2 = ['opacity', 'backgroundColor']
const animateTypes3 = ['width', 'height', 'left', 'right', 'top', 'bottom']
animateTypes1.concat(animateTypes2, animateTypes3).forEach(type => {
	MPAnimation.prototype[type] = function(...args) {
		// #ifndef APP-NVUE
		this.animation[type](...args)
		// #endif
		// #ifdef APP-NVUE
		this._nvuePushAnimates(type, args)
		// #endif
		return this
	}
})

export function createAnimation(option, _this) {
	if(!_this) return
	clearTimeout(_this.timer)
	return new MPAnimation(option, _this)
}