做爲一款2C下單小程序,產品老總說要搞一個加入購物車的動畫,第一習慣是網上找解決方案:貝塞爾算法+setInterval=>setData。html
上線一段時間就出現了加入購物車總價計算負數狀況,以及計算不許,嗯。包括動畫頻繁setData期間丟失關鍵動做setData,以及添加劇復商品等bug。算法
WXS響應事件的基礎庫要求有些高,直接放棄了。小程序
貝塞爾曲線算法 + setInterval=>setDataapi
function bezier(points, part) {
let sx = points[0]['x'];
let sy = points[0]['y'];
let cx = points[1]['x'];
let cy = points[1]['y'];
let ex = points[2]['x'];
let ey = points[2]['y'];
var bezier_points = [];
// 起始點到控制點的x和y每次的增量
var changeX1 = (cx - sx) / part;
var changeY1 = (cy - sy) / part;
// 控制點到結束點的x和y每次的增量
var changeX2 = (ex - cx) / part;
var changeY2 = (ey - cy) / part;
//循環計算
for (var i = 0; i <= part; i++) {
// 計算兩個動點的座標
var qx1 = sx + changeX1 * i;
var qy1 = sy + changeY1 * i;
var qx2 = cx + changeX2 * i;
var qy2 = cy + changeY2 * i;
// 計算獲得此時的一個貝塞爾曲線上的點
var lastX = qx1 + ((qx2 - qx1) * i) / part;
var lastY = qy1 + ((qy2 - qy1) * i) / part;
// 保存點座標
var point = {};
point['x'] = lastX;
point['y'] = lastY;
bezier_points.push(point);
}
//console.log(bezier_points)
return {
bezier_points
};
}
複製代碼
而後 setInterval (坑)網絡
綜合貝塞爾曲線和wx.createAnimationide
method:{
touchOnGoods(e) {
// 若是good_box正在運動
if (!this.data.hide_good_box) return;
const { touches } = e;
const topPoint = {};
this.finger = {
x: touches[0].clientX,
y: touches[0].clientY
};
topPoint['y'] =
this.finger['y'] < this.busPos['y']
? this.finger['y'] - 150
: this.busPos['y'] - 150;
topPoint['x'] =
this.finger['x'] > this.busPos['x']
? (this.finger['x'] - this.busPos['x']) / 2 + this.busPos['x']
: (this.busPos['x'] - this.finger['x']) / 2 + this.finger['x'];
const result = bezier([this.finger, topPoint, this.busPos], 25);
this.startAnimation(result);
},
startAnimation(linePos) {
const { bezier_points } = linePos;
const len = bezier_points.length - 1;
const first = bezier_points.shift();
//防止動畫不生效
//同一個按鈕動畫,動畫開始前先歸位元素位置
this.setData(
{
hide_good_box: false,
initLeft:first.x,
initTop:first.y,
animationData: this.animation.export()
},
() => {
bezier_points.forEach((i, idx) => {
this.animation
.left(i.x)
.top(i.y)
.rotate(50)
.step({ duration: 25 });
});
this.setData({
animationData: this.animation.export()
});
}
);
//有個bug,就是連續點擊,動畫不出來
setTimeout(() => {
this.setData({ hide_good_box: true });
}, len * 20 + 100);
}
},
ready() {
this.busPos = { x: 50, y: 601 };
//調用同步接口 略有問題
this.busPos.y = util.getSysInfo().windowHeight - 66;
this.animation = wx.createAnimation({
timingFunction: 'ease-in',
delay: 0,
duration: 1000
});
}
//有點懶,直接貼源代碼了
複製代碼
<view class="good_box" hidden="{{hide_good_box}}" style="left:{{initLeft}}px;top:{{initTop}}px" animation="{{animationData}}"></view>
<view bindtap="touchOnGoods">
<slot></slot>
</view>
複製代碼
其實好的解決方案,應該是排除低端手機,尤爲是安卓機子來啓用動畫。 暫時沒有其餘好的idea了,由於不多搞動畫,缺少經驗。有同行仁兄多多指交。優化