<template>
<div class="bsx-swipe">
<div class="bsx-swipe-button" :style="{height}">
<slot name="button"></slot>
</div>
<div class="flex1"
ref="content"
@click="hide"
shouldStopPropagation="true"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend">
<slot name="content"></slot>
</div>
</div>
</template>
<script>
import config from './config';
const dom=weex.requireModule('dom');
const animation=weex.requireModule('animation');
export default {
name:'bsx-swipe',
props:{
/*
* 回调额外参数
*/
args:{
type:Object,
default:config.args
}
},
data(){
return {
width:0,
height:0,
startX:0,
startY:0,
opened:false,
isMoving:false
}
},
mounted(){
this.$nextTick(()=>{
this.getContentSize(this.$slots.content[0].elm,size=>{
this.height=Math.floor(size.height);
});
this.getContentSize(this.$slots.button[0].elm,size=>{
this.width=size.width;
});
});
},
methods:{
hide(){
if(this.opened){
this.isMoving=true;
return new Promise((resolve,reject)=>{
this.scrollTo(0,300,()=>{
this.isMoving=false;
this.opened=false;
resolve();
});
});
};
},
show(){
if(!this.opened){
this.isMoving=true;
return new Promise((resolve,reject)=>{
this.scrollTo(this.width,300,()=>{
this.isMoving=false;
this.opened=true;
resolve();
});
});
};
},
touchstart(event){
this.startX=event.changedTouches[0].screenX;
this.startY=event.changedTouches[0].screenY;
this.isMoving=true;
},
touchmove(event){
if(!this.isMoving||(this.startY-event.changedTouches[0].screenY>=5)){
return this.isMoving=false;
};
let distance=this.startX-event.changedTouches[0].screenX;
if(this.opened){
distance+=this.width;
};
if(distance>0){
this.scrollTo(distance,0);
};
},
touchend(event){
let targetX=this.startX-event.changedTouches[0].screenX,
distance=0;
if(this.opened){
if(targetX>0){
distance=this.width;
};
}else{
if(targetX>0&&targetX>=this.width*0.5){
distance=this.width;
};
};
this.scrollTo(distance,distance>5?300:0,()=>{
this.isMoving=false;
this.opened=distance!=0;
this.$emit('onSwiped',{
args:this.args,
status:this.opened
});
});
},
scrollTo(x,time,fn){
this.setAnimation(this.$refs.content,{
scrollX:x,
duration:time,
timingFunction:time===0?null:'ease-out',
callback:fn
});
},
setAnimation(ref,{scrollX,duration,timingFunction,callback}){
animation.transition(ref,{
styles:{
transform:`translateX(${-scrollX}px)`
},
duration:duration||0,
timingFunction:timingFunction||'linear',
needLayout:false,
delay:0
},()=>{
callback&&callback();
});
},
getContentSize(el,fn){
let sid=setInterval(()=>next(),100);
let next=()=>{
dom.getComponentRect(el,res=>{
if(res.result){
fn&&fn(res.size);
}else{
next();
};
});
clearInterval(sid);
};
}
}
};
</script>
<style lang="scss" scoped>
@import 'src/js/css/base.scss';
.bsx-swipe{
background-color: #fff;
overflow: hidden;
}
.bsx-swipe-button{
position: absolute;
right: 0;
top:0;
bottom:0;
}
</style>
setInterval()
javascript方法;
setInterval()按照指定周期不停的调用函数,直到调用clearInterval()或窗口被关闭为止;getComponentRect(ref, callback)
weex方法;
@ref,要滚动到的那个节点。
@callback,异步方法,通过回调返回信息。
获取某个元素 View 的外框;Math.floor()
javascript方法;
对数进行下舍入。stopPropagation
weex方法;
用于内嵌处理Native滑动冲突的情况,阻止Native事件进行冒泡传递。
shouldStopPropagationInitResult 默认初始化false/true的结果
shouldStopPropagationInterval 默认数字类型,控制touch频率,减少JS和Native通信次数,提升流畅性。
转载于:https://www.jianshu.com/p/0f121625ac0a