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
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>
|