<template>
<view
><canvas
canvas-id="bubble"
:style="{ width: width + 'px', height: height + 'px' }"
class="like-fx"
></canvas>
</view>
</template>
<script>
export default {
props: {
count: {
type: Number,
value: 0,
},
height: {
type: Number,
value: 248,
},
width: {
type: Number,
value: 110,
},
},
data() {
return {
queue: {},
timer: 0,
ctx: null,
};
},
onReady() {
this.ctx = wx.createCanvasContext("bubble", this);
this.queue = {};
},
detached() {
if (this.timer) {
clearTimeout(this.timer);
}
},
watch: {
count(newVal, oldVal) {
if (newVal - oldVal > 0) {
this.likeClick();
}
},
immediate: true,
deep: true,
},
methods: {
likeClick() {
const image =
"../../../static/images/" +
this.getRandomInt(1, 4) +
".png";
const anmationData = {
id: new Date().getTime(),
timer: 0,
opacity: 0.5,
pathData: this.generatePathData(),
image: image,
factor: {
speed: 0.004,
t: 0,
},
};
if (Object.keys(this.queue).length > 0) {
this.queue[anmationData.id] = anmationData;
} else {
this.queue[anmationData.id] = anmationData;
this.bubbleAnimate();
}
},
getRandom(min, max) {
return Math.random() * (max - min) + min;
},
getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
generatePathData() {
let width = this.width,
height = this.height;
const p0 = {
x: 0.65 * width,
y: height,
};
const p1 = {
x: this.getRandom(0.22 * width, 0.33 * width),
y: this.getRandom(0.5 * height, 0.75 * height),
};
const p2 = {
x: this.getRandom(0, 0.88 * width),
y: this.getRandom(0.25 * height, 0.5 * height),
};
const p3 = {
x: this.getRandom(0, 0.88 * width),
y: this.getRandom(0, 0.125 * height),
};
return [p0, p1, p2, p3];
},
updatePath(data, factor) {
const p0 = data[0];
const p1 = data[1];
const p2 = data[2];
const p3 = data[3];
const t = factor.t;
const cx1 = 3 * (p1.x - p0.x);
const bx1 = 3 * (p2.x - p1.x) - cx1;
const ax1 = p3.x - p0.x - cx1 - bx1;
const cy1 = 3 * (p1.y - p0.y);
const by1 = 3 * (p2.y - p1.y) - cy1;
const ay1 = p3.y - p0.y - cy1 - by1;
const x = ax1 * (t * t * t) + bx1 * (t * t) + cx1 * t + p0.x;
const y = ay1 * (t * t * t) + by1 * (t * t) + cy1 * t + p0.y;
return {
x,
y,
};
},
bubbleAnimate() {
let width = this.width,
height = this.height;
Object.keys(this.queue).forEach((key) => {
const anmationData = this.queue[+key];
const { x, y } = this.updatePath(
anmationData.pathData,
anmationData.factor
);
const speed = anmationData.factor.speed;
anmationData.factor.t += speed;
var curWidth = 30;
curWidth = (height - y) / 1.5;
curWidth = Math.min(30, curWidth);
var curAlpha = anmationData.opacity;
curAlpha = y / height;
curAlpha = Math.min(1, curAlpha);
this.ctx.globalAlpha = curAlpha;
var _that = this;
_that.ctx.drawImage(
anmationData.image,
x - curWidth / 2,
y,
curWidth,
curWidth
);
if (anmationData.factor.t > 1) {
delete this.queue[anmationData.id];
}
if (y > height) {
delete this.queue[anmationData.id];
}
});
this.ctx.draw();
if (Object.keys(this.queue).length > 0) {
this.timer = setTimeout(() => {
this.bubbleAnimate();
}, 5);
} else {
clearTimeout(this.timer);
this.ctx.draw();
}
},
},
};
</script>
<style scoped>
.like-fx {
position: absolute;
bottom: 72rpx;
right: 0;
z-index: 10;
}
</style>
<view class="t-zan">
<view
class="m-tool m-tool-zan"
:class="[{ animation: isanimation }]"
@tap.prevent="dianZan(true)"
></view>
<likeFx :count="num" width="55" height="128" />
</view>

