1、預期效果?
2、實現思路
每次點擊添加按鈕時,往該按鈕上方添加一個懸浮元素,通過位移動畫將元素移到目標位置。
1. 為每個點擊元素設置不同的class,才能通過uni.createSelectorQuery來獲取每個元素的節點信息;
2. 添加一個與點擊元素一模一樣的動畫元素;
3. 獲取點擊元素的節點信息將動畫元素放置到點擊元素上方;
4. 計算動畫元素到目標位置的距離,獲得xy坐標執行位移動畫;
5. 等待每個動畫元素執行動畫完畢后移除該元素。
3、核心代碼
<template><view><!-- 商品列表 --><view v-for="item in goodsList" :key="item.id"><view :class="[`add-cart-${item.id}`]" @click="addToCart(item)">加購</view></view><!-- 動畫元素列表 --><viewv-for="item in anims" :key="item.key"style="position: fixed; transition: transform 0.5s linear;":style="{top: `${item.top}px`,left: `${item.left}px`,transform: `translate(${item.x}px, ${item.y}px)`,}">加購</view></view>
</template><script setup lang="ts">
import { ref } from 'vue';
import uniqueId from 'lodash-es/uniqueId';const sys = uni.getSystemInfoSync();
const anims = ref<any[]>([]);
const goodsList = ref([{ id: 1 }, { id: 2 }, { id: 3 }])function addToCart(item) {// 添加動畫元素const key = uniqueId();anims.value.push({key,id: item.id,left: 0,top: 0,y: 0,x: 0,});// 獲取點擊元素的節點信息uni.createSelectorQuery().select(`.add-cart-${item.id}`).boundingClientRect((e: any) => {// 初始化起始位置anims.value.some((citem) => {if (citem.key === key) {citem.top = e.top;citem.left = e.left;return true;}return false;});nextTick(() => {// 設置目標位置anims.value.some((citem) => {if (citem.key === key) {citem.y = sys.windowHeight - citem.top - 50;citem.x = -sys.windowWidth * 0.30;setTimeout(() => { // 等待動畫執行完畢移除元素anims.value.splice(anims.value.findIndex((v: any) => v.key === key), 1);}, 500);return true;}return false;});});}).exec();
}</script>