提交 e040aec8 编写于 作者: Q qiang

feat: 增加 uni.createAnimation 接口支持;组件支持 animation 属性

上级 84887cae
const defaultOption = {
duration: 400,
timingFunction: 'linear',
delay: 0,
transformOrigin: '50% 50% 0'
}
class MPAnimation {
constructor (option) {
this.actions = []
this.currentTransform = {}
this.currentStepAnimates = []
this.option = Object.assign({}, defaultOption, option)
}
_getOption (option) {
let _option = {
transition: Object.assign({}, this.option, option)
}
_option.transformOrigin = _option.transition.transformOrigin
delete _option.transition.transformOrigin
return _option
}
_pushAnimates (type, args) {
this.currentStepAnimates.push({
type: type,
args: args
})
}
_converType (type) {
return type.replace(/[A-Z]/g, text => {
return `-${text.toLowerCase()}`
})
}
_getValue (value) {
return typeof value === 'number' ? `${value}px` : value
}
export () {
const actions = this.actions
this.actions = []
return {
actions
}
}
step (option) {
this.currentStepAnimates.forEach(animate => {
if (animate.type !== 'style') {
this.currentTransform[animate.type] = animate
} else {
this.currentTransform[`${animate.type}.${animate.args[0]}`] = animate
}
})
this.actions.push({
animates: Object.values(this.currentTransform),
option: this._getOption(option)
})
this.currentStepAnimates = []
return this
}
}
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) {
if (animateTypes2.concat(animateTypes3).includes(type)) {
this._pushAnimates('style', [this._converType(type), animateTypes3.includes(type) ? this._getValue(args[0]) : args[0]])
} else {
this._pushAnimates(type, args)
}
return this
}
})
export function createAnimation (option) {
return new MPAnimation(option)
}
import Vue from 'vue' import Vue from 'vue'
import baseMixin from 'uni-mixins/base' import baseMixin from 'uni-mixins/base'
import animation from 'uni-mixins/animation'
const requireComponents = [ const requireComponents = [
// baseComponents // baseComponents
...@@ -17,9 +18,11 @@ requireComponents.forEach((components, index) => { ...@@ -17,9 +18,11 @@ requireComponents.forEach((components, index) => {
componentConfig.mixins = componentConfig.mixins ? [].concat(baseMixin, componentConfig.mixins) : [baseMixin] componentConfig.mixins = componentConfig.mixins ? [].concat(baseMixin, componentConfig.mixins) : [baseMixin]
componentConfig.mixins.push(animation)
componentConfig.name = 'VUni' + componentConfig.name componentConfig.name = 'VUni' + componentConfig.name
// 全局注册组件 // 全局注册组件
Vue.component(componentConfig.name, componentConfig) Vue.component(componentConfig.name, componentConfig)
}) })
}) })
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)
}
}
...@@ -47,7 +47,6 @@ export default [ ...@@ -47,7 +47,6 @@ export default [
'stopBeaconDiscovery', 'stopBeaconDiscovery',
'setBackgroundColor', 'setBackgroundColor',
'setBackgroundTextStyle', 'setBackgroundTextStyle',
'createAnimation',
'loadFontFace', 'loadFontFace',
'getProvider', 'getProvider',
'login', 'login',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册