blob: ff8ba1c4c2e1f4e9db2092e6fde44671c04c4f7b [file] [log] [blame]
<!-- CopyRight (C) 2017-2022 WeexUI Group Holding Limited. -->
<!-- Created by git@zwwill on 18/02/08. -->
<template>
<refresh class="wxc-refresher"
@refresh="onRefresh"
@pullingdown="onPullingDown"
:display="refreshing ? 'show' : 'hide'">
<div v-if="newStyleFlag" class="cycle-container" ref="cycle">
<div class="u-cover c1" ref="cover1">
<div class="u-cover-cycle cover1"></div>
</div>
<div class="u-cover c2" ref="cover2">
<div class="u-cover-cycle" ref="cover-cycle"></div>
</div>
</div>
<image v-if="newStyleFlag"
class="arrow-down"
ref="arrow"
:src="ICON_ARROW_DOWN"
resize="contain"></image>
<loading-indicator v-else class="indicator"></loading-indicator>
<text class="u-txt" :style="{width:`${textWidth}px`}">{{refresherText}}</text>
</refresh>
</template>
<script>
const animation = weex.requireModule('animation');
// 减少打包体积
import bindingx from 'weex-bindingx/lib/index.weex';
import BindEnv from '../utils/bind-env';
import Utils from '../utils';
const ICON_ARROW_DOWN = 'https://img.alicdn.com/tfs/TB1A8faeTtYBeNjy1XdXXXXyVXa-48-48.png';
export default {
props: {
scrollerRef: String,
maxTime: {
type: Number,
default: 0
},
mainText: {
type: String,
default: '下拉即可刷新...'
},
pullingText: {
type: String,
default: '释放即可刷新...'
},
refreshingText: {
type: String,
default: '加载中...'
},
textWidth: {
type: Number,
default: 200
}
},
data () {
return {
ICON_ARROW_DOWN,
refreshing: false,
couldUnLash: false
}
},
computed: {
newStyleFlag () {
return this.scrollerRef && BindEnv.supportsEBForIos();
},
refresherText () {
return this.refreshing ? this.refreshingText : this.pText;
},
pText () {
return this.couldUnLash ? this.pullingText : this.mainText;
}
},
created () {
this.newStyleFlag && this.animationBinding();
},
beforeDestroy () {
this.bindingsDestroy();
},
methods: {
onRefresh (event) {
this.$emit('wxcRefresh', event);
this.refreshing = true;
this.newStyleFlag && this.cycleGoRound();
if (this.maxTime <= 0) return;
this.timeoutSto && clearTimeout(this.timeoutSto);
this.timeoutSto = setTimeout(() => {
this.$emit('wxcTimeout');
this.wxcCancel();
}, this.maxTime);
},
/**
* 取消 refreshing
*/
wxcCancel () {
this.refreshing = false;
this.timeoutSto && clearTimeout(this.timeoutSto);
this.roundingDestroy();
},
/**
* 下拉事件
*/
onPullingDown (event) {
this.$emit('wxcPullingDown',event);
let pd = event.pullingDistance * (Utils.env.isIOS() ? -1 : 1);
pd > (Utils.env.isAndroid() ? 200 : 140) ? (this.couldUnLash = true) : (this.couldUnLash = false);
if (this.refreshing && pd < 20) {
this.timeoutSto && clearTimeout(this.timeoutSto);
this.refreshing = false;
this.roundingDestroy();
}
},
/**
* 注册 bindingx
*/
animationBinding () {
setTimeout(() => {
// 降级版本取不到,需要注意
const scroller = this.$parent.$refs[this.scrollerRef].ref;
const cover2 = this.$refs['cover2'].ref;
const coverCycle = this.$refs['cover-cycle'].ref;
const bindingResult = bindingx.bind({
eventType: 'scroll',
anchor: scroller,
props: [
{
element: cover2,
property: 'transform.rotateZ',
expression: 'y>-140?(y%75/150*-360):156'
},
{
element: coverCycle,
property: 'opacity',
expression: 'y<-75 ?1:0'
}
]
}, (e) => {});
this.bindingToken = bindingResult.token;
}, 300);
},
/**
* 旋转动作
*/
cycleGoRound () {
if (Utils.env.isAndroid()) return;
let cycle = this.$refs['cycle'].ref;
this.arrowShow(false);
if (!cycle) {
return;
}
const roundingResult = bindingx.bind({
eventType: 'timing',
props: [
{
element: cycle,
property: 'transform.rotateZ',
expression: 't*0.72'
}
]
}, (e) => {
});
this.roundingToken = roundingResult.token;
},
/**
* 箭头显隐控制
*/
arrowShow (_show = true) {
const arrow = this.$refs['arrow'];
arrow && animation.transition(arrow, {
styles: {
opacity: _show ? 1 : 0,
transform: _show ? "scale(1)" : "scale(0.5)"
},
duration: 300,
delay: 0
}, () => {
});
},
/**
* 完整 bindingx 销毁
*/
bindingsDestroy () {
if (this.bindingToken !== 0) {
bindingx && bindingx.unbind({
eventType: 'scroll',
token: this.bindingToken
});
this.bindingToken = 0;
}
this.roundingDestroy();
},
/**
* 旋转 bindingx 销毁
*/
roundingDestroy () {
if (this.roundingToken !== 0) {
bindingx && bindingx.unbind({
eventType: 'timing',
token: this.roundingToken
});
this.roundingToken = 0;
}
this.arrowShow(true);
}
}
}
</script>
<style scoped>
.wxc-refresher {
height: 140px;
width: 750px;
flex-direction: row;
/* flex-wrap: nowrap; */
justify-content: center;
padding-top: 50px;
}
.cycle-container {
position: relative;
width: 60px;
height: 60px;
}
.u-cover {
position: absolute;
width: 30px;
height: 60px;
top: 0;
background-color: #ffffff;
overflow: hidden;
right: 0;
}
.c1 {
z-index: 1;
}
.c2 {
z-index: 2;
transform-origin: left center;
transform: rotateZ(0deg);
}
.u-cover-cycle {
position: absolute;
width: 60px;
height: 60px;
right: 0;
top: 0;
/* box-sizing: border-box; */
border-width: 2px;
border-color: #666666;
border-style: solid;
border-radius: 30px;
opacity: 0;
}
.cover1 {
opacity: 1;
}
.indicator {
margin-right: 20px;
height: 60px;
width: 60px;
color: #666666;
}
.arrow-down {
position: relative;
top: 15px;
left: -45px;
width: 30px;
height: 30px;
}
.u-txt {
font-size: 24px;
line-height: 40px;
color: #999999;
margin-top: 10px;
margin-left: 10px;
height: 40px;
lines: 1;
}
</style>