You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

229 lines
5.8 KiB

<template>
<view class="hx-jump-ball">
<view class="ballBox" :animation="ballBoxAnimationData" :style="{'z-index':index}">
<view class="ballOuter"
:animation="ballOuterAnimationData"
:style="{width:ballWidth*2 + 'upx',height:ballHeight*2 + 'upx','background-color':backgroundColor,'background-image': backgroundImage ?`url(${backgroundImage})`: ''}">
</view>
</view>
</view>
</template>
<script>
export default {
name: "hx-jump-ball",
data() {
return {
flag: false,
ballBoxAnimation: null,
ballOuterAnimation: null,
ballBoxAnimationData: {},
ballOuterAnimationData: {},
};
},
props: {
//小球宽度
ballWidth: {
type: Number,
default: 15
},
//小球高度
ballHeight: {
type: Number,
default: 15
},
//小球颜色
backgroundColor: {
type: String,
default: "reg"
},
//图片
backgroundImage: {
type: String,
default: ""
},
//小球的堆叠顺序
index: {
type: Number,
default: 0
},
//开始动画
start: {
type: Number,
default: 1
},
//html元素class名称,[起点元素,终点元素]
element:{
type: Array,
default(){
return []
}
},
//下落速度 ms毫秒
speed:{
type: Number,
default: 800
},
//贝塞尔曲线
bezier:{
type: String,
default: "cubic-bezier(.6,-0.63,.94,.71)"
}
},
watch:{
start(val,oldVal) {
var that = this;
if(!that.element){
return;
}
if(this.flag){
return;
}
that.flag = !that.flag;
that.getElementCoordinate(that.element[0],that.element[1]);
}
},
created() {
this.ballBoxAnimation = uni.createAnimation({
duration: 0,
timingFunction: this.bezier,
delay: 0
});
this.ballOuterAnimation = uni.createAnimation({
duration: 0,
timingFunction: "linear",
delay: 0
});
this.setEnd();
//初始化位置
},
methods:{
//获取元素坐标
getElementCoordinate(startElement,endElement){
let that = this;
const query = uni.createSelectorQuery();
let nodesRef = query.select(startElement);
nodesRef.fields({
id: true,
rect: true,
size: true
}, res => {
if(!res){
that.flag = !that.flag;
that.$emit("msg",{code: 100, error: '未获取到起始元素位置'})
return ;
}
const SLeft = res.left + ((res.width + that.ballWidth ) / 2 - that.ballWidth);
const STop = res.bottom - ((res.height - that.ballHeight ) / 2 + that.ballHeight);
let nodesRef2 = uni.createSelectorQuery().select(endElement);
nodesRef2.fields({
id: true,
rect: true,
size: true
}, res2 => {
if(!res2){
that.$emit("msg",{code: 101, error: '未获取到结束元素位置'})
return ;
}
//计算出元素的中心坐标
let ELeft = res2.left + ((res2.width + that.ballWidth ) / 2 - that.ballWidth);
let ETop = res2.bottom - ((res2.height - that.ballHeight ) / 2 + that.ballHeight);
//初始化位置
that.setStart(SLeft,STop,ELeft,ETop);
that.startAnimation(SLeft,STop,ELeft,ETop);
}).exec()
}).exec()
},
//开始动画
startAnimation(SLeft,STop,ELeft,ETop){
let that = this;
let jumpDistance = SLeft - ELeft;
setTimeout(function() {
that.setEnd();
that.flag = !that.flag;
that.$emit("msg",{code:0,status:true});
}, 100 + that.speed);
// 暂时注释掉,待uniapp修复bug后再调整
//根坐标
// this.ballBoxAnimation.translate3d(ELeft,STop,0).step({duration: 800});
// this.ballBoxAnimation.translate3d(ELeft,ETop,0).step({duration: 800});
// this.ballBoxAnimationData = this.ballBoxAnimation.export();
// console.log('根坐标执行玩');
// //相对根的坐标
// this.ballOuterAnimation.translate3d(jumpDistance,0,0).step({duration: 800});
// this.ballOuterAnimation.translate3d(0,0,0).step({duration: 800});
// this.ballOuterAnimationData = this.ballOuterAnimation.export();
// console.log('相对根的坐标');
// setTimeout(function() {
// console.log("动画完成");
// that.flag = !that.flag;
// }, 800);
//因为uniapp step()有bug,所以必须要延时执行
setTimeout(function() {
//根坐标
that.ballBoxAnimation.opacity(1).translate3d(ELeft,ETop,0).step({duration: that.speed});
that.ballBoxAnimationData = that.ballBoxAnimation.export();
//相对根的坐标
that.ballOuterAnimation.opacity(1).translate3d(0,0,0).step({duration: that.speed});
that.ballOuterAnimationData = that.ballOuterAnimation.export();
}, 50);
},
//动画开始前初始化小球位置并显示小球
setStart(SLeft,STop,ELeft,ETop){
this.ballBoxAnimation.translate3d(ELeft,STop,0).opacity(1).step({duration: 0});
this.ballBoxAnimationData = this.ballBoxAnimation.export();
this.ballOuterAnimation.translate3d(SLeft - ELeft,0,0).opacity(1).step({duration: 0});
this.ballOuterAnimationData = this.ballOuterAnimation.export();
},
//隐藏小球
setEnd(){
this.ballBoxAnimation.opacity(0).step({duration: 0});
this.ballBoxAnimationData = this.ballBoxAnimation.export();
this.ballOuterAnimation.opacity(0).step({duration: 0});
this.ballOuterAnimationData = this.ballOuterAnimation.export();
}
}
}
</script>
<style>
.ballBox{
position: fixed;
left: 0;
top: 0;
z-index: 9;
/* 用颜色来演示用原理 */
/*background-color: #4CD964*/;
height:30rpx;
width:30rpx;
}
.ballOuter {
background:red;
height:100%;
width:100%;
border-radius: 50%;
background-size: 100% 100%;
background-position: center;
}
</style>