- 小程序特殊发货报备,写了单号还提示请输入单号
[图片]
2023-11-30 - 微信小程序中实现丝滑的加购动画
前言 大家在商城类小程序中经常会看到如下图的加购动画,丝滑的抛物线动画进入购物车的过程给用户带来了更好的购物体验~ 这样的动画其实需要考虑到很多情况,要不然就很容易出现问题。 [图片] 在接下来的文章中,我们将手把手教会大家实现这样的功能。 二、技术分析 2.1 现象剖析 首先简单的看下整个加购动画的过程,小球的出现是从用户点击处产生的,随即完成一个抛物线后,进入金额处(购物车),最后购物车产生放大效果。 我们通常实现动画的方式一般就是两种,第一种就是js 控制运行的轨迹,第二种就是css实现。js实现的话势必会出现性能问题,在某些边界情况下会出现卡顿,作为前端人员想必大家都知道~ 如果使用css实现的话,我们需要解决以下几个问题: 如何确认和设置小球的初始位置?如何实现一个抛物线的动画?如何知道抛物线动画结束了?并通知购物车发生抖动和放大效果?2.2 分步实现 1.加购小球 我们知道在小程序中是没有办法动态创建一个节点的,所以小球是需要在当前页面事先准备好,以一个组件身份存在~ 小球组件的初始位置由用户点击位置进行决定,所以小球的position必须是个变量,让我们想到了css变量~ 组件接收外部两个属性 showBall控制显隐position,通过style去定义css var变量从而设置小球初始位置如下是简单的小球组件代码: // animationBall.wxml // animationBall.wxss .ball-box { width: 20rpx; height: 20rpx; border-radius: 100%; position: fixed; z-index: 10; left: var(--startX); top: var(--startY); } // animationBall.js Component({ properties: { showBall: { type: Boolean, value: false }, position: { type: Object, value: { } } }, observers: { "position.startX, position.startY": function(startX, startY) { let style = `--startX:${startX}px;--startY:${startY}px;--endX: 15vw;--endY: 92vh`; this.setData({ style }); } } }); 2.页面点击事件 我们在页面中添加小球组件,并且给加购点击动作添加事件~ 这样当我们点击时候就可以初始化小球的位置以及让小球展示出来 // 购买页面点击事件 buy.js buy(event){ this.setData({ "position.startX": event.touches[0].clientX, "position.startY": event.touches[0].clientY, showBall: true }); } // buy.wxml 3.animation动画拆解 我们确定了小球的初始位置和终点位置(终点位置是固定的,这里不赘述了),接下来就是需要去剖析抛物线动画~ 一个抛物线整体去看,会比较没有头目,但是我们可以从某个单一维度去看整个小球运动的过程,然后再将这几个维度的动画组合起来,就可以完成整个动画的设计。我们分成三个维度,分别是y轴的位移、x轴的位移、小球大小、小球透明度。 1.y轴位移:小球先有一小段的上升,上升到最高点,这一段y轴位移一直在增加,我们给它动画叫做throwTopY,接下来抛物线下降,这个过程y轴一直在减少,一直减少到我们终点为止,我们叫做throwDropY。 // animationBall.wxss @keyframes throwTopY { 0% { top: var(--startY); } 100% { top: calc(var(--startY) - 120rpx); } } @keyframes throwDropY { 0% { top: calc(var(--startY) - 120rpx); } 100% { top: var(--endY); } } 2.x轴位移:小球x轴的位移在整个运动过程中都是从右向左变化的,我们认为一直是在线性变化的,我们动画称为throwX。 // animationBall.wxss @keyframes throwX { 0% { left: var(--startX); } 100% { left: var(--endX); } } 3.小球大小:小球大小在整个过程中,上升阶段是变大的,我们称为scaleTop, 当下降的时候小球一直在变小,称为scaleDrop。 // animationBall.wxss @keyframes scaleSize { 0% { width: 20rpx; height: 20rpx; } 100% { width: 10rpx; height: 10rpx; } } 4.小球透明度:小球的透明度在初始阶段时候是能看到的,然后再接下来的过程是慢慢变成透明,直到完全透明,我们称showAndHide @keyframes showAndHide { 0% { opacity: 1; } 90% { opacity: 0.9; } 100% { opacity: 0; } } 按照以上的分析,单个维度的动画都已经写出来了,剩下来就是将他们组合在一起,组合的核心就是动画时间、动画曲线(贝塞尔曲线)以及动画停留在哪里~ 假设整个动画的过程是需要0.5秒,上升过程我们假定0.2秒,下降的过程0.3秒 我们先用伪代码写出思路来,思考0.2秒的动画中发生了什么事情? y轴位移变大小球变大所以这个0.2秒发生了 = throwTopY + scaleTop 0.3秒发生了什么事情? y轴位移变小小球变小所以这个0.3秒发生了 = throwDropY + scaleDrop 那么整体的0.5秒钟x轴和透明度其实也发生了变化,0.5秒的throwX,0.5秒的showAndHide 思路有了之后,代码其实就已经出来了 // animationBall.wxss .animationBall { animation-fill-mode: forwards; animation: throwTopY 0.2s cubic-bezier(0, 0.3, 0.3, 1) forwards, scaleTop 0.2s cubic-bezier(0.48, 0.33, 0.24, 1.18) forwards, throwDropY 0.3s cubic-bezier(0.7, 0, 1, 0.7) 0.2s forwards, scaleDrop 0.3s cubic-bezier(0.48, 0.33, 0.24, 1.18) 0.2s forwards, throwX 0.46s linear forwards, showAndHide 0.5s linear forwards; } // animationBall.wxml <view class="ball-box animationBall" wx:if="{{showBall}}" style="{{style}}"></view> 上诉中涉及到贝赛尔曲线问题,这块大家自行了解下,不是本篇文章重点。 至此我们完成了小球抛物线动画的实现,不过还有个问题,我们如何知道小球完成了抛物线,并且通知到当前页面的购物车,让购物车发生抖动或者变大的效果呢?重点就在于如何通知动画完成~ 我们可以对小球绑定一个监听动画的事件bindanimationend,这个事件代表最后一个动画结束,我们最后一个动画是showAndHide,所以我们通过此去进行判断即可,抛出事件后,页面获取到再做后续购物车的变化(这块也不是重点,本篇文章忽略) // animationBall.wxml <view bindanimationend="observeAnimation" class="ball-box animationBall" wx:if="{{showBall}}" style="{{style}}"> </view> // animationBall.js watchAnimation(res) { // 最后一组动画结束 抛出事件通知外部 if (res?.detail?.animationName === "showAndHide") { this.triggerEvent("animationHasDone"); } } 以上就是所有的内容了,按照这样操作,你也可以实现丝滑的加购动画啦~
2023-10-25