2023-09-21 14:49:07 +08:00

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
})
}
}
}