添加到购物车抛物线动画
发布于 6 年前 作者 songyong 6449 次浏览 来自 问答

哪位大神晓得 小程序如何实现 添加到购物车的抛物线动画

类似 jquery.fly.min.js

DEMO示例:http://www.sucaihuo.com/jquery/0/1/demo/

JQ的方法是创建demo,而小程序无法创建demo

求教…

10 回复

是的,所以现阶段就挑可以做的功能做吧。这个功能你可以跟上司反馈一下问题。

问题在于,加入购物车按钮不是固定位置的,所以需要计算,用keyframe可能无法满足要求。

所以现在的问题在于,使用 wx:if 或 hidden 属性的时候,动画无法执行。

确实太麻烦了,这个问题也只能期待后续会尽快完善

总之,就是微信方面做的不够完善,各种情况没有考虑到,一味的为了异步而异步,没有考虑过同步、异步间的协作问题,所以,我的建议是,使用Canvas可以实现,但是实现起来比较复杂。

说错了,不用赋值到style上,直接通过获得的位置,创建个元素,定上去,然后执行动画

我给每一个商品都加了个ID,点击的时候 用wx.createSelectorQuery()去查询这个ID获取位置,然后赋值到style上,再用@keyframe 去执行动画,初始不设置位置,只设置了 100%的最终位置

我感觉严格的抛物线动画不能通过createAnimation实现,但是可以通过帧动画。

这是我之前写的抛物线组件:

ts:

Component({

data: {

left: 0,

top: 0,

hidden: true,

},

timer: 0,

detached() {

this.cancel();

},

pageLifetimes: {

hide() {

this.cancel();

},

},

methods: {

animate(options: IOptions & { onEnd: () => void }) {

const { onEnd } = options;

this.cancel(false);

this.setData({

left: options.start.x,

top: options.start.y,

hidden: false,

});

parabolaAnimate(options, ({ x, y }, timer) => {

this.setData({ left: x, top: y });

this.timer = timer;

if (timer === 0) {

this.setData({ hidden: true });

if (typeof onEnd === ‘function’) {

onEnd();

}

}

});

},

cancel(hidden = true) {

if (this.timer) {

clearInterval(this.timer);

this.timer = 0;

}

if (hidden) {

this.setData({ hidden: true });

}

},

},

});

interface IOptions {

start: { x: number; y: number };

end: { x: number; y: number };

topY: number;

gforce?: number;

frameDuration?: number;

}

function parabolaAnimate(

options: IOptions,

callback: (ponit: { x: number; y: number }, timer: number) => void

) {

const { start, end, topY, gforce = 2000, frameDuration = 10 } = options;

const tStartToTop = Math.sqrt((Math.abs(topY - start.y) * 2) / gforce);

const tTopToEnd = Math.sqrt((Math.abs(topY - end.y) * 2) / gforce);

const tFrame = frameDuration / 1000;

let tRest = tStartToTop + tTopToEnd;

let vx = (end.x - start.x) / (tStartToTop + tTopToEnd);

let vy = -gforce * tStartToTop;

let startX = start.x;

let startY = start.y;

let timer = setInterval(() => {

const ponit = {

x: startX + vx * tFrame,

y: startY + vy * tFrame + (gforce * tFrame * tFrame) / 2,

};

vy = vy + gforce * tFrame;

tRest = tRest - tFrame;

startX = ponit.x;

startY = ponit.y;

if (tRest <= 0) {

clearInterval(timer);

timer = 0;

}

callback(ponit, timer);

}, frameDuration);

}

wxml:

<view hidden="{{hidden}}" class=“parabola-ball” style=“left:{{left}}px;top:{{top}}px;”></view>

调用:

Page({

onReady() {

this.parabolaBall = this.selectComponent("#parabola-ball");

this.systemInfo = wx.getSystemInfoSync();

},

animateBall(e) {

const { screenHeight, screenWidth } = this.systemInfo;

const { clientX, clientY } = e.touches[0];

const start = {

x: clientX,

y: clientY

};

this.parabolaBall.animate({

start,

end: {

x: screenWidth * 0.62,

y: screenHeight + 30

},

topY: clientY + 50

});

}

});

备注:重点在于抛物线函数parabolaAnimate的算法,其中起点坐标,终点坐标,顶点y坐标,重力加速度值是决定抛物线轨迹的必须要素。

你这么做有另一个问题就出现了。

你在同一个商品上连续快速的点击几次,会发现明显的闪跳。

如果使用 wx:for 来动态生成移动图片的话,就不会有问题了。

只可惜……还是上面的Bug……哎。

用 wx:for 生成的话,有这样的问题微信待解决:

生成后的动画状态无法保存,在增加或删除元素的时候,wx:for 会将所有元素的状态清除,未完成的动画直接消失。

好吧,我最近研究了,只能实现 图片到购物车的直线移动,

@keyframe 实现的,做成抛物线曲线运动,确实没法做

回到顶部