<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>
the setInterval ()
JavaScript method;
the setInterval () calls the specified function stop period, until the clearInterval call (), or until the window is closed;getComponentRect (ref, callback)
weex method;
@ref, to scroll to that node.
@callback, asynchronous methods return information via callback.
View acquiring an element of the frame;Math.floor ()
JavaScript method;
the logarithm rounded.the stopPropagation
With weex, method;
for the case of conflict embedded processing Native slide, to prevent bubbling Native event delivery.
shouldStopPropagationInitResult default initialization false / true result
shouldStopPropagationInterval default numeric type, control the frequency of touch, reducing the number of communications and Native JS, enhance fluency.
Reproduced in: https: //www.jianshu.com/p/0f121625ac0a