悬浮球组件
<template>
<view
class="hover_ball_cell"
:style="{ width: `${diameter}px`, height: `${diameter}px`, top: `${top}px`, left: `${left}px` }"
@touchmove.prevent="touchmove"
@touchend="touchend"
@touchcancel="touchcancel"
@tap="onTap"
:animation="ballAnimation"
>
<view v-if="iconUrl == ''" class="wave" />
<image v-else :src="iconUrl" mode=""></image>
</view>
</template>
<script>
export default {
props: {
iconUrl: {
type: String,
default: ''
},
onClickHover: {
type: Function,
require: true,
default: null,
},
},
data() {
return {
diameter: 0,
top: 0,
left: 0,
isMove: false,
ballAnimation: {},
timeout: null,
modile: {},
};
},
name: 'hover-ball',
created() {
let _this = this;
_this.modile = uni.getSystemInfoSync();
_this.top = _this.modile.safeArea.height - 180;
_this.left = _this.modile.safeArea.width;
_this.diameter = _this.modile.screenHeight / 15;
let create = uni.createAnimation({
duration: 400,
timingFunction: 'ease-in'
});
create.translate('-100%').step();
setTimeout(() => {
create.translate('-50%').step();
_this.ballAnimation = create.export();
}, 0)
},
methods: {
onTap() {
let _this = this;
let x = '0';
if (2 * _this.left >= _this.modile.safeArea.width) {
x = '-100%';
}
let create = uni.createAnimation({
duration: 0
});
create.translate(x).step();
_this.ballAnimation = create.export();
_this.overBall();
_this.onClickHover()
},
touchmove(e) {
let _this = this;
_this.isMove = true;
if (_this.timeout != null) {
clearTimeout(_this.timeout);
_this.timeout = null;
}
var touch = e.touches[0] || e.changedTouches[0];
_this.left = touch.clientX;
_this.top = touch.clientY;
},
touchend(e) {
let _this = this;
if (!_this.isMove) {
return;
}
_this.finish(e);
},
touchcancel(e) {
let _this = this;
if (!_this.isMove) {
return;
}
_this.finish(e);
},
finish(e) {
let _this = this;
_this.isMove = false;
var touch = e.touches[0] || e.changedTouches[0];
_this.left = touch.clientX;
_this.top = touch.clientY;
let x = '0';
if (2 * _this.left + _this.diameter >= _this.modile.safeArea.width) {
_this.left = _this.modile.safeArea.width;
x = '-100%';
} else {
_this.left = _this.modile.safeArea.left;
}
if (_this.top > _this.modile.safeArea.height + _this.modile.safeAreaInsets.bottom) {
_this.top = _this.modile.safeArea.height + _this.modile.safeAreaInsets.bottom;
} else if (_this.top < - _this.diameter / 2) {
_this.top = - _this.diameter / 2;
}
let create = uni.createAnimation({
duration: 0
});
console.log(x)
create.translate(x).step();
_this.ballAnimation = create.export();
_this.overBall();
},
overBall() {
let _this = this;
_this.timeout = setTimeout(() => {
_this.timeout = null;
let create = uni.createAnimation({
duration: 400,
timingFunction: 'ease-in'
});
create.translate('-50%').step();
_this.ballAnimation = create.export();
}, 1200);
}
}
};
</script>
<style lang="less" scoped>
.hover_ball_cell {
position: fixed;
overflow: hidden;
border-radius: 50%;
border: 4rpx solid #67c23a;
background: #ffffff;
transform: translate(-50%, 0);
padding: 4rpx;
display: flex;
justify-content: center;
align-items: center;
z-index: 100000;
.wave {
position: relative;
width: 100%;
height: 100%;
background-image: linear-gradient(-180deg, #aaff80 13%, #67c23a 91%);
border-radius: 50%;
}
image{
width: 60%;
height: 60%;
}
}
</style>
使用组件
<template>
<view class="version">
<hover-ball :onClickHover="onClickHover" :iconUrl="iconUrl"/>
</view>
</template>
<script>
export default {
data() {
return {
iconUrl: '../../static/image/shopping-cart.png'
};
},
onLoad(option) {
},
onShow() {
},
methods: {
onClickHover(){
uni.$u.route('/pages/secondary/shopping-cart');
},
}
};
</script>
<style scoped lang="scss">
</style>