更新记录
1.0.1(2025-04-12)
下载此版本
增加插槽使用说明
1.0.0(2025-04-11)
下载此版本
新增组件
平台兼容性
App |
快应用 |
微信小程序 |
支付宝小程序 |
百度小程序 |
字节小程序 |
QQ小程序 |
HBuilderX 3.1.0 |
× |
√ |
× |
× |
× |
× |
钉钉小程序 |
快手小程序 |
飞书小程序 |
京东小程序 |
鸿蒙元服务 |
× |
× |
× |
× |
× |
H5-Safari |
Android Browser |
微信浏览器(Android) |
QQ浏览器(Android) |
Chrome |
IE |
Edge |
Firefox |
PC-Safari |
× |
× |
× |
× |
× |
× |
× |
× |
× |
hbxw-shop-cart-ani 购物车动画组件
购物车动画组件,可用于购物车商品飞入动画效果。
使用示例
推荐先直接复制示例代码到工程中看效果了解下使用方法再投入项目使用。
<template>
<view class="container">
<!-- 商品列表 -->
<!-- 通过实例调用 推荐,这样可以节省元素数量,所有添加到购物车共用一个组件 -->
<view class="goods-list">
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
<image class="goods-image" :src="item.image" mode="aspectFill"></image>
<view class="goods-action">
<view class="goods-info">
<text class="goods-name">{{item.name}}</text>
<text class="goods-price">¥{{item.price}}</text>
</view>
<view class="goods-action-btn" @tap="addToCart(item, $event)">添加到购物车</view>
</view>
</view>
</view>
<!-- 组件直接包含子元素,子元素会被作为触发元素 -->
<view class="goods-item">
<image class="goods-image" src="https://dummyimage.com/400x400/000/fff.png&text=test_img" mode="aspectFill"></image>
<view class="goods-action">
<view class="goods-info">
<text class="goods-name">商品0</text>
<text class="goods-price">168</text>
</view>
<hbxw-shop-cart-ani :item="{'test': 12345}" :targetX="cartLeft" :targetY="cartTop" @end="onAniEnd">
<view class="goods-action-btn">添加到购物车</view>
</hbxw-shop-cart-ani>
</view>
</view>
<!-- 购物车按钮 -->
<view class="cart-btn" :style="{left: cartLeft + 'px', top: cartTop + 'px'}">
<text class="cart-num" v-if="cartNum > 0">{{cartNum}}</text>
<text class="iconfont icon-cart">🛒</text>
</view>
<!-- 动画组件 -->
<hbxw-shop-cart-ani ref="cartAni" :targetX="cartLeft" :targetY="cartTop" @end="onAniEnd">
<template #aniItem>
<view class="ani-ball"></view>
</template>
</hbxw-shop-cart-ani>
</view>
</template>
<script>
export default {
data() {
return {
// 购物车位置
cartLeft: 300,
cartTop: 600,
// 购物车数量
cartNum: 0,
// 商品列表
goodsList: [
{
id: 1,
name: '商品1',
price: 99,
image: 'https://dummyimage.com/400x400/000/fff.png&text=test_img'
},
{
id: 2,
name: '商品2',
price: 199,
image: 'https://dummyimage.com/400x400/000/fff.png&text=test_img'
},
{
id: 3,
name: '商品3',
price: 299,
image: 'https://dummyimage.com/400x400/000/fff.png&text=test_img'
},
{
id: 4,
name: '商品4',
price: 399,
image: 'https://dummyimage.com/400x400/000/fff.png&text=test_img'
}
]
}
},
methods: {
// 添加到购物车
addToCart(item, event) {
// 获取点击位置
const { x, y } = event.detail
// 开始动画
this.$refs.cartAni.start(x, y)
},
// 动画结束
onAniEnd() {
this.cartNum++
}
}
}
</script>
<style>
.container {
padding: 20rpx;
}
.goods-list {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.goods-item {
width: 45%;
margin-bottom: 20rpx;
background: #fff;
border-radius: 12rpx;
overflow: hidden;
box-shadow: 0 2rpx 12rpx rgba(0,0,0,0.1);
}
.goods-image {
width: 100%;
height: 200rpx;
}
.goods-info {
padding: 16rpx;
}
.goods-name {
font-size: 28rpx;
color: #333;
}
.goods-price {
font-size: 32rpx;
color: #f00;
margin-top: 8rpx;
display: block;
}
.cart-btn {
position: fixed;
width: 80rpx;
height: 80rpx;
background: #f00;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.cart-num {
position: absolute;
top: -6rpx;
right: -6rpx;
min-width: 32rpx;
height: 32rpx;
line-height: 32rpx;
text-align: center;
background: #ff0;
color: #f00;
border-radius: 16rpx;
font-size: 24rpx;
padding: 0 6rpx;
}
.icon-cart {
color: #fff;
font-size: 40rpx;
}
.ani-ball {
width: 30rpx;
height: 30rpx;
background: #f00;
border-radius: 50%;
}
.goods-action{
display: flex;
justify-content: space-between;
align-items: center;
}
.goods-action-btn{
background-color: mediumslateblue;
font-size: 12px;
text-align: center;
padding: 8px;
color: #fff;
border-radius: 4px
}
</style>
参数说明
参数名 |
类型 |
默认值 |
说明 |
targetX |
Number |
0 |
目标点X坐标(屏幕绝对位置,单位px) |
targetY |
Number |
0 |
目标点Y坐标(屏幕绝对位置,单位px) |
duration |
Number |
600 |
动画时长(ms) |
item |
Object |
null |
关联商品数据对象 |
事件说明
插槽说明
插槽名 |
说明 |
default |
默认插槽,用于包裹触发动画的元素 |
aniItem |
自定义动画元素的样式,不设置则使用默认样式 |
坐标获取说明
// 在onReady生命周期获取目标位置
onReady() {
const query = uni.createSelectorQuery().in(this);
query.select('#cartIcon').boundingClientRect(data => {
this.cartPos = {
x: data.left + data.width/2,
y: data.top + data.height/2
}
}).exec()
}