546 lines
18 KiB
JavaScript
546 lines
18 KiB
JavaScript
const Binding = uni.requireNativePlugin('bindingx')
|
|
const animation = uni.requireNativePlugin('animation')
|
|
const dom = uni.requireNativePlugin('dom')
|
|
import Util from '../../js_sdk/util.js'
|
|
export default {
|
|
data () {
|
|
return {
|
|
disableTouch: false,
|
|
isTouch: false,
|
|
touchTime: 0,
|
|
interval: false,
|
|
loadingType: '',
|
|
direction: ''
|
|
}
|
|
},
|
|
beforeDestroy () {
|
|
if ( this.flipBinding ) {
|
|
Binding.unbind({
|
|
token: this.flipBinding.token,
|
|
eventType: 'pan'
|
|
})
|
|
this.sliderBinding = null
|
|
}
|
|
this.resetFlipAnimationBinding()
|
|
},
|
|
methods: {
|
|
fliptouchstart (event) {
|
|
if ( this.isTouch || this.disableTouch ) {
|
|
return
|
|
}
|
|
this.isTouch = true
|
|
this.touchTime = 0
|
|
this.interval = true
|
|
this.setInterval()
|
|
let touch = event.touches[0]
|
|
this.startX = touch.pageX
|
|
this.startY = touch.pageY
|
|
},
|
|
fliptouchmove (event) {
|
|
if ( this.isTouch && !this.disableTouch ) {
|
|
let touch = event.touches[0]
|
|
let offset = this.vertical ? touch.pageY - this.startY : touch.pageX - this.startX
|
|
if ( !this.direction ) {
|
|
if ( Math.abs(offset) < this.sliderFault ) return
|
|
if ( offset < 0 ) {
|
|
if ( this.nextIndex < this.count && this.nextIndex != 0 ) {
|
|
if ( this.type != 'none' ) {this.direction = 'next'}
|
|
} else if ( this.pullupable && this.loadingState != 'loading' && this.loadingState != 'success' && this.loadingState != 'fail' ) {
|
|
this.loadingType = 'pullup'
|
|
this.disableTouch = true
|
|
this.clearInterval()
|
|
this.pulling()
|
|
}
|
|
} else {
|
|
if ( this.prevIndex > -1 && this.prevIndex != this.count - 1 ) {
|
|
if ( this.type != 'none' ) {this.direction = 'prev'}
|
|
} else if ( this.pulldownable && this.loadingState != 'loading' && this.loadingState != 'success' && this.loadingState != 'fail' ) {
|
|
this.loadingType = 'pulldown'
|
|
this.disableTouch = true
|
|
this.clearInterval()
|
|
this.pulling()
|
|
}
|
|
}
|
|
}
|
|
if ( this.direction ) {
|
|
this.disableTouch = true
|
|
this.flipTouchAction()
|
|
} else {
|
|
this.resetPageBinding()
|
|
}
|
|
}
|
|
},
|
|
async fliptouchend (e) {
|
|
if ( this.isTouch && !this.disableTouch ) {
|
|
let rect = await this.getRect(this.$refs.yingbingFlip)
|
|
let size = this.vertical ? rect.height : rect.width
|
|
this.clearInterval()
|
|
let start = this.vertical ? this.startY : this.startX
|
|
if ( this.touchTime <= 200 && (!this.unableClickPage || this.type == 'none') ) {
|
|
if (start > (size / 4) * 3 && this.nextIndex < this.count && this.nextIndex != 0 ) {
|
|
this.flipToNextBindingX()
|
|
} else if (start < (size / 4) && this.prevIndex >= 0 && this.prevIndex != this.count - 1 ) {
|
|
this.flipToPrevBindingX()
|
|
} else {
|
|
this.resetPageBinding()
|
|
}
|
|
} else {
|
|
this.resetPageBinding()
|
|
}
|
|
}
|
|
},
|
|
async flipTouchAction () {
|
|
let props = []
|
|
let rect = await this.getRect(this.$refs.yingbingFlip)
|
|
let size = this.vertical ? rect.height : rect.width
|
|
let translate = this.translate
|
|
let shadowProperty = this.vertical ? 'height' : 'width'
|
|
let key = this.vertical ? 'y' : 'x'
|
|
if ( this.direction == 'prev' ) {
|
|
if ( this.prevIndex > -1 ) {
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItem_' + this.prevIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `${key} < 0 ? ${-size} : (${key} > ${size} ? 0 : ${key}-${size})`
|
|
})
|
|
if ( this.type == 'real' ) {
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemContent_' + this.prevIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `${key} < 0 ? ${size} : (${key} > ${size} ? 0 : ${size}-${key})`
|
|
})
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemBg_' + this.prevIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `${key} < 0 ? 0 : (${key} > ${size} ? ${size} : ${key} + 0)`
|
|
})
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemShadow_' + this.prevIndex),
|
|
property: shadowProperty,
|
|
expression: `${size} / 2 - abs(${key}) / 2'`
|
|
})
|
|
}
|
|
}
|
|
} else {
|
|
if ( this.nextIndex < this.count ) {
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItem_' + this.nextIndex),
|
|
property: 'transform.' + translate,
|
|
expression: '0+0'
|
|
})
|
|
}
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItem_' + this.currentIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `${key} > 0 ? 0 : (${key} < ${-size} ? ${-size} : ${key} + 0)`
|
|
})
|
|
if ( this.type == 'real' ) {
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemContent_' + this.currentIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `${key} > 0 ? 0 : (${key} < ${-size} ? ${size} : 0 - ${key})'`
|
|
})
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemBg_' + this.currentIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `${key} > 0 ? ${size} : (${key} < ${-size} ? 0 : ${key}+${size})`
|
|
})
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemShadow_' + this.currentIndex),
|
|
property: shadowProperty,
|
|
expression: `abs(${key})/2+0`
|
|
})
|
|
}
|
|
}
|
|
this.flipBinding = Binding.bind({
|
|
anchor: this.getEl('yingbingFlip'),
|
|
eventType: 'pan',
|
|
props: props
|
|
}, (e) => {
|
|
if ((e.state == 'end' || e.state == 'cancel') && this.flipBinding) {
|
|
this.clearInterval()
|
|
Binding.unbind({
|
|
token: this.flipBinding.token,
|
|
eventType: 'pan'
|
|
})
|
|
this.flipBinding = null
|
|
let value = this.direction == 'next' ? 1 : -1;
|
|
if (this.touchTime <= 200) {
|
|
this.pageAnimation(-value * size, size);
|
|
} else {
|
|
let index = this.direction == 'next' ? this.currentIndex : this.prevIndex
|
|
let deltaX = Binding.getComputedStyle(this.getEl('yingbingFlipItem_' + index))[translate]
|
|
let offset = this.direction == 'next' ? Math.abs(deltaX) : size - Math.abs(deltaX)
|
|
if ( offset >= size / 4) {
|
|
this.pageAnimation(-value * size, size)
|
|
} else {
|
|
this.pageAnimation(0, size);
|
|
}
|
|
}
|
|
}
|
|
})
|
|
},
|
|
flipToNextBindingX () {
|
|
if ( !this.disableTouch && this.nextIndex < this.count && (this.nextIndex != 0 || this.circular) ) {
|
|
this.direction = 'next'
|
|
this.flipToBindingX()
|
|
}
|
|
},
|
|
flipToPrevBindingX () {
|
|
if ( !this.disableTouch && this.prevIndex >= 0 && (this.prevIndex != this.count - 1 || this.circular) ) {
|
|
this.direction = 'prev'
|
|
this.flipToBindingX()
|
|
}
|
|
},
|
|
async flipToBindingX () {
|
|
this.disableTouch = true
|
|
let value = this.direction == 'next' ? 1 : -1;
|
|
let rect = await this.getRect(this.$refs.yingbingFlip)
|
|
let size = this.vertical ? rect.height : rect.width
|
|
this.pageAnimation(-value * size, size)
|
|
},
|
|
getRect (el) {
|
|
return new Promise(resolve => {
|
|
dom.getComponentRect(el, res => {
|
|
resolve(res.size)
|
|
})
|
|
})
|
|
},
|
|
setInterval () {
|
|
this.touchTimer = setTimeout(() => {
|
|
this.touchTime += 10
|
|
if ( this.interval ) {
|
|
this.setInterval()
|
|
}
|
|
}, 10)
|
|
},
|
|
clearInterval () {
|
|
this.interval = false
|
|
if ( this.touchTimer ) {
|
|
clearTimeout(this.touchTimer)
|
|
this.touchTimer = null
|
|
}
|
|
},
|
|
pageAnimation (offset, size) {
|
|
let duration = this.type == 'none' ? 0.1 : this.duration
|
|
let late = offset
|
|
let translate = this.translate
|
|
let shadowProperty = this.vertical ? 'height' : 'width'
|
|
let props = []
|
|
if ( this.direction == 'prev' ) {
|
|
if ( this.prevIndex > -1 ) {
|
|
let itemTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItem_' + this.prevIndex))[translate]
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItem_' + this.prevIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `linear(t, ${itemTrans}, ${late - size - itemTrans}, ${duration})`
|
|
})
|
|
if ( this.type == 'real' ) {
|
|
let contentTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemContent_' + this.prevIndex))[translate]
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemContent_' + this.prevIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `linear(t, ${contentTrans}, ${-(late - size) - contentTrans}, ${duration})`
|
|
})
|
|
let bgTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemBg_' + this.prevIndex))[translate]
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemBg_' + this.prevIndex),
|
|
property: 'transform.' + translate,
|
|
expression: `linear(t, ${bgTrans}, ${late - bgTrans}, ${duration})`
|
|
})
|
|
let shadowSize = Binding.getComputedStyle(this.getEl('yingbingFlipItemShadow_' + this.prevIndex))[shadowProperty] || size
|
|
props.push({
|
|
element: this.getEl('yingbingFlipItemShadow_' + this.prevIndex),
|
|
property: shadowProperty,
|
|
expression: `linear(t, ${shadowSize}, ${-(late - size) - shadowSize}, ${duration})`
|
|
})
|
|
}
|
|
this.flipAnimationBinding = Binding.bind({
|
|
eventType: 'timing',
|
|
exitExpression: 't>' + duration,
|
|
props: props
|
|
}, (e) => {
|
|
if (e.state == 'exit' && this.flipAnimationBinding && e.t > duration) {
|
|
Binding.unbind({
|
|
token: this.flipAnimationBinding.token,
|
|
eventType: 'timing'
|
|
})
|
|
this.flipAnimationBinding = null
|
|
if ( Math.abs(offset) > 0 ) {
|
|
this.handleFlipChange(this.direction == 'next' ? 1 : -1)
|
|
this.$nextTick(function () {
|
|
this.resetPageBinding()
|
|
})
|
|
} else {
|
|
this.resetPageBinding();
|
|
}
|
|
}
|
|
})
|
|
}
|
|
} else {
|
|
if ( this.nextIndex < this.count ) {
|
|
animation.transition(this.getRef('yingbingFlipItem_' + this.nextIndex), {
|
|
styles: {
|
|
transform: `${translate}(0)`
|
|
},
|
|
duration: 0,
|
|
timingFunction: 'linear',
|
|
needLayout: true
|
|
})
|
|
}
|
|
animation.transition(this.getRef('yingbingFlipItem_' + this.currentIndex), {
|
|
styles: {
|
|
transform: `${translate}(${late}px)`
|
|
},
|
|
duration: duration,
|
|
timingFunction: 'linear',
|
|
needLayout: true
|
|
}, () => {
|
|
if ( Math.abs(offset) > 0 ) {
|
|
this.handleFlipChange(this.direction == 'next' ? 1 : -1)
|
|
this.$nextTick(function () {
|
|
this.resetPageBinding()
|
|
})
|
|
} else {
|
|
this.resetPageBinding();
|
|
}
|
|
})
|
|
if ( this.type == 'real' ) {
|
|
animation.transition(this.getRef('yingbingFlipItemContent_' + this.currentIndex), {
|
|
styles: {
|
|
transform: `${translate}(${-late}px)`
|
|
},
|
|
duration: duration,
|
|
timingFunction: 'linear',
|
|
needLayout: true
|
|
})
|
|
animation.transition(this.getRef('yingbingFlipItemBg_' + this.currentIndex), {
|
|
styles: {
|
|
transform: `${translate}(${size + late}px)`
|
|
},
|
|
duration: duration,
|
|
timingFunction: 'linear',
|
|
needLayout: true
|
|
})
|
|
let styles = {}
|
|
styles[shadowProperty] = -late + 'px'
|
|
animation.transition(this.getRef('yingbingFlipItemShadow_' + this.currentIndex), {
|
|
styles: styles,
|
|
duration: duration,
|
|
timingFunction: 'linear',
|
|
needLayout: true
|
|
})
|
|
}
|
|
// if ( this.nextIndex < this.count ) {
|
|
// props.push({
|
|
// element: this.getEl('yingbingFlipItem_' + this.nextIndex),
|
|
// property: 'transform.' + translate,
|
|
// expression: '0+0'
|
|
// })
|
|
// }
|
|
// let itemTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItem_' + this.currentIndex))[translate]
|
|
// props.push({
|
|
// element: this.getEl('yingbingFlipItem_' + this.currentIndex),
|
|
// property: 'transform.' + translate,
|
|
// expression: `linear(t, ${itemTrans}, ${late - itemTrans}, ${duration})`
|
|
// })
|
|
// if ( this.type == 'real' ) {
|
|
// let contentTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemContent_' + this.currentIndex))[translate]
|
|
// props.push({
|
|
// element: this.getEl('yingbingFlipItemContent_' + this.currentIndex),
|
|
// property: 'transform.' + translate,
|
|
// expression: `linear(t, ${contentTrans}, ${-late - contentTrans}, ${duration})`
|
|
// })
|
|
// let bgTrans = Binding.getComputedStyle(this.getEl('yingbingFlipItemBg_' + this.currentIndex))[translate]
|
|
// props.push({
|
|
// element: this.getEl('yingbingFlipItemBg_' + this.currentIndex),
|
|
// property: 'transform.' + translate,
|
|
// expression: `linear(t, ${bgTrans}, ${size + late - bgTrans}, ${duration})`
|
|
// })
|
|
// let shadowSize = Binding.getComputedStyle(this.getEl('yingbingFlipItemShadow_' + this.currentIndex))[shadowProperty]
|
|
// props.push({
|
|
// element: this.getEl('yingbingFlipItemShadow_' + this.currentIndex),
|
|
// property: shadowProperty,
|
|
// expression: `linear(t, ${shadowSize}, ${-late - shadowSize}, ${duration})`
|
|
// })
|
|
// }
|
|
}
|
|
},
|
|
pulling () {
|
|
let loadingType = this.loadingType
|
|
let size = loadingType == 'pullup' ? this.pullupHeight : this.pulldownHeight
|
|
let key = this.vertical ? 'y' : 'x'
|
|
let translate = this.translate
|
|
let props = [
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType),
|
|
property: 'transform.' + translate,
|
|
expression: loadingType == 'pullup' ? `abs(${key}) > ${size} ? 0 : ${key} + ${size}` : `abs(${key}) > ${size} ? 0 : ${key} - ${size}`
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_default'),
|
|
property: 'opacity',
|
|
expression: `abs(${key}) < ${size} ? 1 : 0`
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_ready'),
|
|
property: 'opacity',
|
|
expression: `abs(${key}) < ${size} ? 0 : 1`
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_loading'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_success'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_fail'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
}
|
|
]
|
|
this.flipBinding = Binding.bind({
|
|
anchor: this.getEl('yingbingFlip'),
|
|
eventType: 'pan',
|
|
props: props
|
|
}, (e) => {
|
|
if ((e.state == 'end' || e.state == 'cancel') && this.flipBinding) {
|
|
Binding.unbind({
|
|
token: this.flipBinding.token,
|
|
eventType: 'pan'
|
|
})
|
|
this.flipBinding = null
|
|
let deltaX = Binding.getComputedStyle(this.getEl('yingbing_flip_' + loadingType))[translate]
|
|
if ( deltaX == 0 ) {
|
|
this.loadingState = 'ready'
|
|
this.pullingRefreshBindingx()
|
|
} else {
|
|
this.loadingState = 'default'
|
|
this.resetPullingBindingx()
|
|
}
|
|
}
|
|
})
|
|
},
|
|
resetPullingBindingx () {
|
|
let loadingType = this.loadingType
|
|
let translate = this.translate
|
|
let size = loadingType == 'pullup' ? this.pullupHeight : this.pulldownHeight
|
|
let trans = loadingType == 'pullup' ? size : -size
|
|
let deltaX = Binding.getComputedStyle(this.getEl('yingbing_flip_' + loadingType))[translate]
|
|
let duration = 300
|
|
let props = [
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType),
|
|
property: 'transform.' + translate,
|
|
expression: `linear(t, ${deltaX}, ${trans}, ${duration})`
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_default'),
|
|
property: 'opacity',
|
|
expression: this.loadingState == 'default' ? '1+0' : '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_ready'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_loading'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_success'),
|
|
property: 'opacity',
|
|
expression: this.loadingState == 'success' ? '1+0' : '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_fail'),
|
|
property: 'opacity',
|
|
expression: this.loadingState == 'fail' ? '1+0' : '0+0'
|
|
}
|
|
]
|
|
this.flipAnimationBinding = Binding.bind({
|
|
eventType: 'timing',
|
|
exitExpression: 't>' + duration,
|
|
props: props
|
|
}, (e) => {
|
|
if (e.state == 'exit' && this.flipAnimationBinding && e.t > duration) {
|
|
this.resetFlipAnimationBinding()
|
|
this.loadingState = ''
|
|
this.resetPageBinding()
|
|
}
|
|
})
|
|
},
|
|
pullingRefreshBindingx () {
|
|
let loadingType = this.loadingType
|
|
let duration = 1
|
|
let props = [
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_default'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_ready'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_loading'),
|
|
property: 'opacity',
|
|
expression: '1+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_success'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
},
|
|
{
|
|
element: this.getEl('yingbing_flip_' + loadingType + '_fail'),
|
|
property: 'opacity',
|
|
expression: '0+0'
|
|
}
|
|
]
|
|
this.flipAnimationBinding = Binding.bind({
|
|
eventType: 'timing',
|
|
exitExpression: 't>' + duration,
|
|
props: props
|
|
}, (e) => {
|
|
if (e.state == 'exit' && this.flipAnimationBinding && e.t > duration) {
|
|
this.resetFlipAnimationBinding()
|
|
this.pullingRefresh(loadingType)
|
|
}
|
|
})
|
|
},
|
|
resetFlipAnimationBinding () {
|
|
if ( this.flipAnimationBinding ) {
|
|
Binding.unbind({
|
|
token: this.flipAnimationBinding.token,
|
|
eventType: 'timing'
|
|
})
|
|
this.flipAnimationBinding = null
|
|
}
|
|
},
|
|
getEl (selector) {
|
|
return this.$refs[selector] ? Util.getEl(this.$refs[selector].length > 0 ? this.$refs[selector][0] : this.$refs[selector]) : null
|
|
},
|
|
getRef (selector) {
|
|
return this.$refs[selector] ? this.$refs[selector].length > 0 ? this.$refs[selector][0] : this.$refs[selector] : null
|
|
},
|
|
resetPageBinding () {
|
|
this.direction = ''
|
|
this.touchTime = 0
|
|
this.startX = 0
|
|
this.startY = 0
|
|
this.$nextTick(function () {
|
|
this.isTouch = false
|
|
this.disableTouch = false
|
|
})
|
|
}
|
|
}
|
|
} |