zengh
2022-05-09 52c39f5e2711e5535b689b66dfa5e100c7882b7f
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
const BindingX = uni.requireNativePlugin('bindingx');
const animation = weex.requireModule('animation');
const modal = weex.requireModule('modal');
export default {
    data(){
        return{
            typeX:false, //是否开启左右滑动
            playCount:2,//剩余多少视频加载视频列表
            startDistance:5, //开启左右滑动时有效,判断左右上下拖动的启动距离
            minTime:300, //判断为快速滑动的时间,该时间内无视回弹
            backDistance:200, //上下滑动的回弹距离
            oldTime:0,
            oldTouces:{},
            touchType:null,
            gesToken:0,
            height:'667px',
            index:0,
            oldIndex:0,
            width:'',
            sysheight:0,
            distance:0,
            distanceX:0,
            scroll:false,
        }
    },
    created(){
        //#ifdef APP-PLUS
            plus.screen.lockOrientation("portrait-primary")
        //#endif
        this.sysheight = uni.getSystemInfoSync().windowHeight
        this.height = `${this.sysheight}px` 
        let width = uni.getSystemInfoSync().windowWidth 
        this.width = `${width}px` 
    },
    methods:{
        getEl: function(el) {
            if (typeof el === 'string' || typeof el === 'number') return el;
            if (WXEnvironment) {
                return el.ref;
            } else {
                return el instanceof HTMLElement ? el : el.$el;
            }
        },
        // ListTouch触摸开始
        ListTouchStart(e) {
            
            this.oldTime = new Date()
            this.oldTouces = e.changedTouches[0]
        },
        ListTouchEnd(e) {
            console.log('end')
        },
        //判定方向
        ListTouchMove(e){
            
            //结束启动判断
            if(this.touchType == 'stop') return
            let { oldTouces,oldValue,touchType } = this
            let newTouces = e.changedTouches[0]
            
            if(!this.touchType){
                let startDistance = this.typeX?this.startDistance: 0 
                
                //滑动启动条件
                this.touchType = Math.abs( newTouces.pageY - oldTouces.pageY ) > startDistance ? 'moveY' : null
                if(this.touchType=='moveY'&&newTouces.pageY> oldTouces.pageY){
                    this.touchType = 'moveYB'
                }else if(this.touchType=='moveY'&&newTouces.pageY<oldTouces.pageY){
                    this.touchType = 'moveYT'
                }
                //是否开启左右滑动
                if(!this.touchType&&this.typeX){
                    this.touchType = newTouces.pageX - oldTouces.pageX > startDistance ? 'moveXR' : this.touchType
                    this.touchType = newTouces.pageX - oldTouces.pageX < -startDistance ? 'moveXL' : this.touchType
                }
                
            }else{
                
                
                // 如果在执行动画,就不触发
                if(this.scroll) return 
                // 解绑动画
                if(this.gesToken != 0) {
                    BindingX.unbind({
                        eventType:'pan',
                        token:this.gesToken
                    })
                    this.gesToken = 0
                    // return
                }
                
                let move
                if(this.touchType == 'moveYB'||this.touchType == 'moveYT'){
                    move = 0
                }else if(this.touchType == 'moveXL'){
                    move = -1
                }else if(this.touchType == 'moveXR'){
                    move = 1
                }
                
                
                
                //关闭启动判断
                this.touchType = 'stop'
                
                let touch_origin = `y+${this.distance}<=0 && ${move}==0 && ${this.distanceX}==0 && 
                    y+${this.distance}-${this.sysheight}>=${-this.sysheight*this.videoList.length}? 
                    y+${this.distance} : ${this.distance}`
                // 找到元素 
                let swiperRef = this.getEl(this.$refs.swiper)
                let leftRef = this.getEl(this.$refs.left)
                let rightRef = this.getEl(this.$refs.right)
                
                let anchor
                if(this.distanceX==0){
                    let touchRef = this.getEl(this.$refs.touch)
                    anchor = touchRef
                }else if(this.distanceX<=0){
                    anchor = rightRef
                }else{
                    anchor = leftRef
                }
                
                let gesTokenObj = BindingX.bind({
                    anchor:anchor,
                    eventType:'pan',
                    props: [
                        {element:swiperRef, property:'transform.translateY',expression: touch_origin},
                        {element:swiperRef, property:'transform.translateX',expression: `${move}!=0 && ${move}*x>0 ?x+${this.distanceX} : ${this.distanceX}`},
                        {element:leftRef, property:'transform.translateX',expression: `${move}!=0&& ${move*this.distanceX}<=0&&x+${this.distanceX}<393?x+${this.distanceX} : ${this.distanceX}`},
                        {element:rightRef, property:'transform.translateX',expression: `${move}!=0&& ${move*this.distanceX}<=0&&x+${this.distanceX}>-393?x+${this.distanceX} : ${this.distanceX}`}
                    ]
                }, (e) => {
                    if(e.state === 'end') {
                        this.touchType = null
                        
                        //上下
                        if(move==0&& this.distanceX==0&& Math.abs(e.deltaY)>this.startDistance){
                            let newTime = new Date()
                            let quickMove = newTime.getTime() - this.oldTime.getTime() <= this.minTime ? true:false
                            
                            // 记录当前坐标
                            const distance = this.distance + e.deltaY
                            
                            if(distance>0 || this.distance + e.deltaY-this.sysheight<-this.sysheight*this.videoList.length) return
                            
                            this.bindTiming(distance,e.deltaY,quickMove)
                        }
                    
                        if(move!=0&& move*this.distanceX<=0&& e.deltaX*this.distanceX<=0&& Math.abs(e.deltaX)>this.startDistance){
                            const distance = this.distanceX + e.deltaX
                            
                            this.bindTimingX(distance,e.deltaX)
                        }
                    }
                })
                // 记录下取消的token 多次 ontouchstart 时要带着 token 把上次的解绑
                this.gesToken = gesTokenObj.token
            }
            
        },
        bindTiming(distance,Y,quickMove){
            BindingX.unbindAll()
            // 开始执行动画
            this.scroll = true
            let swiperRef = this.getEl(this.$refs.swiper)
            let sysheight = this.sysheight
            
            let changed_Y, final_Y, translate_Y_origin
            
            // 生成表达式逻辑
            if( Math.abs(Y)<=this.backDistance&&!quickMove) {
                // 往上下拖动20以内时
                final_Y = this.distance    // 回到原点
                changed_Y = final_Y - distance    // 计算出需要位置的值
                translate_Y_origin = `easeOutExpo(t,${distance},${changed_Y},300)` // 运动曲线为easeOutElastic
            } else{
                // 往上下拖动超过一半时
                final_Y = this.distance + (Y>0?1:-1) *this.sysheight
                changed_Y= final_Y - distance// 计算出需要位置的值
                translate_Y_origin = `easeOutExpo(t,${distance},${changed_Y},600)` // 运动曲线为easeOutExpo
            }
            let result = BindingX.bind({
                eventType:'timing',       // 结束的时候是没有任何监听的 用 timing 来做定时的动画
                exitExpression:"t>600",  // 当时间超过 300ms 结束动画
                props: [
                    {element:swiperRef, property:'transform.translateY',expression:translate_Y_origin},
                    ]
                },async (e) => {
                    if(e.state === 'end' || e.state === 'exit') {
                        this.distance = final_Y
                        this.scroll = false
                        if( Math.abs(Y)>this.backDistance||quickMove) {
                            this.index = -this.distance/this.sysheight
                            for (let item of this.videoList) {
                                item.flag = false
                            }
                            console.log(this.index)
                            this.videoList[this.index].flag = true
                            //加载视频
                            if(this.videoList.length - this.index - 1 <= this.playCount){
                                // await this.pushVideoList()
                            }
                        }else if(Math.abs(Y)<=this.backDistance&&!quickMove){
                            this.videoList[this.index].flag = true
                        }
                    }
            })
        },
        bindTimingX(distance,X){
            // 开始执行动画
            this.scroll = true
            let swiperRef = this.getEl(this.$refs.swiper)
            let leftRef = this.getEl(this.$refs.left)
            let rightRef = this.getEl(this.$refs.right)
            let width = parseInt(this.width) 
            
            let changed_X, final_X, origin
            
            // 生成表达式逻辑
            if( Math.abs(X)<=10) {
                final_X = this.distanceX    // 回到原点
                changed_X = final_X - distance    // 计算出需要位置的值
                origin = `easeOutExpo(t,${distance},${changed_X},300)` // 运动曲线为easeOutElastic
            } else{
                final_X = this.distanceX + (X>0?1:-1) *width
                changed_X= final_X - distance// 计算出需要位置的值
                origin = `easeOutExpo(t,${distance},${changed_X},300)` // 运动曲线为easeOutExpo
            }
            let result = BindingX.bind({
                eventType:'timing',       // 结束的时候是没有任何监听的 用 timing 来做定时的动画
                exitExpression:"t>300",  // 当时间超过 300ms 结束动画
                props: [
                    {element:swiperRef, property:'transform.translateX',expression:origin},
                    {element:swiperRef, property:'transform.translateY',expression:`easeOutExpo(t,${this.distance},0,200)`},
                    {element:leftRef, property:'transform.translateX',expression:origin},
                    {element:rightRef, property:'transform.translateX',expression:origin}
                    ]
                },async (e) => {
                    if(e.state === 'end' || e.state === 'exit') {
                        this.distanceX = final_X
                        this.scroll = false
                        if( Math.abs(X)<=10&&this.distanceX==0){
                            
                        }else if( Math.abs(X)>10&&this.distanceX!=0) {
                            for (let item of this.videoList) {
                                item.flag = false
                            }
                        }else if(Math.abs(X)>10&&this.distanceX==0){
                            this.videoPlay(this.index)
                        }
                        
                    }
            })
        },
        bindCurrentX(current,time=300) {
            if(this.distanceX!=0) return
            this.scroll = true
            let swiperRef = this.getEl(this.$refs.swiper)
            let changed_Y, final_Y, origin
            
            final_Y = this.distance + (this.index-current) *this.sysheight
            changed_Y= final_Y - this.distance // 计算出需要位置的值
            time = time * Math.abs(this.index-current)
            origin = `easeOutExpo(t,${this.distance},${changed_Y},${time})` // 运动曲线为easeOutExpo
        
            
            
            let result = BindingX.bind({
                eventType:'timing', // 结束的时候是没有任何监听的 用 timing 来做定时的动画
                exitExpression:`t>${time}`, // 当时间超过 300ms 结束动画
                props: [
                    {element:swiperRef, property:'transform.translateY',expression:origin},
                ]
                },async (e) => {
                    if(e.state === 'end' || e.state === 'exit') {
                        this.distance = final_Y
                        this.scroll = false
                        
                        
                        this.index = -this.distance/this.sysheight
                        for (let item of this.videoList) {
                            item.flag = false
                        }
                        this.videoList[this.index].flag = true
                        
                        //加载视频
                        if(this.videoList.length - this.index - 1 <= this.playCount){
                            // await this.pushVideoList()
                        }
                        
                        
                    }
                
            })
        },
        pauseVideo(val){
            console.log(this.oldIndex)
             this.videoList[this.oldIndex].initialTime = val
        },
        clickVideo(){
            this.oldIndex = this.index
            this.videoList[this.index].flag = !this.videoList[this.index].flag
        },
        videoPlay(index){
            if(this.distanceX!=0) return
            let promise = new Promise((resolve,reject)=>{
                resolve()
            })
            promise.then(res=>{
                this.videoList[index].flag = !this.videoList[index].flag
            })
        },
    },
    watch:{
        index(newVal,oldVal){
            this.oldIndex = oldVal
        }
    }
}