在UniApp中css实现蚂蚁森林点击抖动效果的完整指南
前言
蚂蚁森林的点击互动动画是提升用户参与感的经典设计。本文通过 UniApp + Vue3 技术栈,结合 CSS 关键帧动画 ,实现高度还原的小树点击抖动效果。
一、效果演示
点击小树后触发连贯动画:
树木呈现弹性缩放效果(Y轴拉伸)
伴随轻微水平位移的拟真抖动
动画结束后平滑恢复初始状态
二、核心实现原理
- 动画关键帧设计
通过 scaleY 纵向缩放模拟拉伸,scaleX 横向补偿形变,结合多阶段关键帧实现弹性效果:
CSS
@keyframes growBounceTree {0% { transform: scaleX(1) scaleY(1); } /* 初始状态 */18% { transform: scaleX(1.04) scaleY(1.18); } /* 最大拉伸 */30% { transform: scaleX(0.98) scaleY(1.08); } /* 回弹阶段1 */45% { transform: scaleX(1.03) scaleY(1.13); } /* 二次拉伸 */60% { transform: scaleX(0.99) scaleY(1.06); } /* 回弹阶段2 */75% { transform: scaleX(1.01) scaleY(1.10); } /* 微调拉伸 */100% { transform: scaleX(1) scaleY(1); } /* 恢复原点 */
}
- 动画绑定与触发
通过 Vue 响应式状态控制动画类名切换:
HTML
<image class="tree-img" :class="{ shake: isShaking }" @click="shakeTree" @animationend="isShaking = false"
/>
JavaScript
const isShaking = ref(false)
const shakeTree = () => {if (!isShaking.value) isShaking.value = true
}
三、关键技术细节
- 形变中心点控制
通过 transform-origin: 50% 100% 设置形变基准点为树木底部,模拟真实植物生长效果:
CSS
.tree-img {transform-origin: 50% 100%; /* x轴居中,y轴底部对齐 */
}
- 动画性能优化
开启 GPU 加速:添加 will-change: transform 提示浏览器预优化
复合动画曲线:使用默认 ease-out 曲线实现自然回弹
避免重复渲染:动画结束后立即移除类名减少内存占用
四、完整实现代码
HTML
<template><view class="tree-demo-container"><image class="tree-img" src="https://p6.itc.cn/q_70/images03/20220108/4fa1d2e8006140fb838fcda2a61259f3.jpeg":class="{ shake: isShaking }" @click="shakeTree" @animationend="isShaking = false" mode="widthFix" /><view class="tip-text">点击小树体验抖动效果</view></view>
</template><script lang="ts" setup>
import { ref } from 'vue'
const isShaking = ref(false)
const shakeTree = () => {if (!isShaking.value) isShaking.value = true
}
</script><style lang="scss" scoped>
.poster-container {padding: 20rpx;display: flex;flex-direction: column;align-items: center;
}.poster-preview {margin: 30rpx auto;width: 100%;display: flex;flex-direction: column;align-items: center;
}.poster-image {width: 100%;box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);border-radius: 20rpx;
}/* 新增树动画样式 */
// .tree-img {
// width: 160rpx;
// height: 220rpx;
// margin-bottom: 30rpx;
// transition: transform 0.1s;
// /* 以底部为中心进行缩放和晃动 */
// transform-origin: 50% 100%;
// }// .shake {
// animation: growBounceTree 0.7s;
// transform-origin: 50% 100%;
// }// @keyframes growBounceTree {
// 0% {
// transform: scaleX(1) scaleY(1) translateY(0);
// }// 20% {
// transform: scaleX(1.05) scaleY(1.18) translateY(-18rpx);
// }// 35% {
// transform: scaleX(0.98) scaleY(1.08) translateY(-10rpx);
// }// 50% {
// transform: scaleX(1.03) scaleY(1.13) translateY(-14rpx);
// }// 65% {
// transform: scaleX(0.99) scaleY(1.06) translateY(-7rpx);
// }// 80% {
// transform: scaleX(1.01) scaleY(1.10) translateY(-10rpx);
// }// 100% {
// transform: scaleX(1) scaleY(1) translateY(0);
// }
// }.poster-image {width: 100%;box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.1);border-radius: 20rpx;/* 新增动画相关属性 */transform-origin: 50% 100%;/* 你可以在JS中动态加shake类来触发动画 */
}.shake {animation: growBounceTree 0.7s;transform-origin: 50% 100%;
}@keyframes growBounceTree {0% {transform: scaleX(1) scaleY(1);}18% {transform: scaleX(1.04) scaleY(1.18);}30% {transform: scaleX(0.98) scaleY(1.08);}45% {transform: scaleX(1.03) scaleY(1.13);}60% {transform: scaleX(0.99) scaleY(1.06);}75% {transform: scaleX(1.01) scaleY(1.10);}100% {transform: scaleX(1) scaleY(1);}
}.canvas-container {position: fixed;left: -9999px;top: -9999px;z-index: -1;
}.poster-canvas {width: 750px;height: 1200px;
}.action-buttons {margin-top: 40rpx;width: 100%;padding: 0 30rpx;
}.save-btn,
.share-btn {margin-top: 30rpx;
}
五、高级扩展技巧
- 复合抖动效果
在现有动画基础上增加水平位移:
CSS
@keyframes growBounceTree {0% { transform: translateX(0) scaleX(1) scaleY(1); }18% { transform: translateX(-3px) scaleX(1.04) scaleY(1.18); }/* ...其余关键帧同步调整... */
}
- 移动端优化方案
禁用点击高亮:
CSS
.tree-img {-webkit-tap-highlight-color: transparent;
}
添加触觉反馈(需调用设备API)
性能分级策略:低端设备减少动画阶段
3. 音效同步播放
JavaScript
const playSound = () => {const audio = uni.createInnerAudioContext()audio.src = '/static/shake-sound.mp3'audio.play()
}const shakeTree = () => {if (!isShaking.value) {isShaking.value = trueplaySound()}
}
六、常见问题排查
现象 解决方案
动画卡顿 检查是否缺少 will-change 或 transformZ(0)
iOS 无效果 确认 HBuilderX 版本 ≥3.4.10
点击无响应 检查图片是否添加 @click 事件绑定
形变位置错误 确认 transform-origin 值是否正确