vue 加入购物车抛物线动画

效果图


购物车主要是两张图,分别是盖子和篮子组成一个图,点击事件默认能获取页面点击X和Y

.vue

typescript 复制代码
<template>
  <view
    v-for="ball in balls"
    :key="ball.id"
    class="ball"
    :style="{
      '--x': `${ball.x - 30}px`,
      '--y': `${ball.y - 20}px`,
    }" />
  <view class="btn wxy-button flex-between">
    <view class="flex">
      <view class="btn-item">
        <image class="btn-item-lid" :src="imgUrl('home/lid')"
               :class="{'btn-item-lid-active': balls.length > 0}" />
        <image class="btn-item-basket" :src="imgUrl('home/basket')" />
      </view>
      <wxy-text-price :num="2.5" :digit="2" />
    </view>
    <view class="wxy-btn flex-center btn-button bg-main round">
      去结算
    </view>
  </view>
</template>

<script setup lang='ts'>
import { imgUrl } from '@/modules/tool'
import { watch, ref } from 'vue'

interface Ball {
  id: number
  x: number
  y: number
}

const props = defineProps({
  location: {
    type: Object,
    default: () => ({
      x: 0,
      y: 0,
    }),
  },
})

const balls = ref<Ball[]>([])
let ballId = 0

watch(() => props.location, (newLoc) => {
  if (newLoc.x !== 0 || newLoc.y !== 0) {
    const newBall: Ball = {
      id: ++ballId,
      x: newLoc.x,
      y: newLoc.y,
    }
    balls.value.push(newBall)

    setTimeout(() => {
      const index = balls.value.findIndex((b) => b.id === newBall.id)
      if (index > -1) {
        balls.value.splice(index, 1)
      }
    }, 800)
  }
})
</script>

<style lang='scss' scoped>
.ball {
  position: absolute;
  top: var(--y);
  left: var(--x);
  z-index: 3;
  width: 48rpx;
  height: 48rpx;
  background-color: var(--main);
  border-radius: 50%;
  animation: fly-to-cart 1s cubic-bezier(0.2, 0.8, 0.2, 1) forwards;
  pointer-events: none;
  will-change: transform;
}

@keyframes fly-to-cart {
  to{
    transform: translate(calc(30rpx - var(--x)), calc(100vh - 100rpx - var(--y))) scale(0.6);
  }
}

.btn{
  padding: 20rpx 30rpx calc(20rpx + (env(safe-area-inset-bottom) / 2));

  &-button{
    width: 280rpx;
    height: 84rpx;
    font-weight: 500;
  }

  &-item{
    --size:166rpx;
    --top:-30rpx;

    width: 110rpx;

    &-lid{
      position: absolute;
      top: var(--top);
      left: 0;
      z-index: 1;
      width: var(--size);
      height: var(--size);
      backface-visibility: hidden;
      transition: .4s ease-in-out;
      will-change: transform;
    }

    &-lid-active{
      transform: rotate(-60deg) translateY(-30rpx) translateX(20rpx);
    }

    &-basket{
      position: absolute;
      top: var(--top);
      left: 0;
      width: var(--size);
      height: var(--size);
    }
  }
}
</style>

遇到问题可以看我主页加我Q,很少看博客,对你有帮助别忘记点赞收藏。

相关推荐
CryptoPP15 分钟前
BSE股票K线数据接入实战:从接口调用到前端图表展示
大数据·前端·网络·人工智能·websocket·网络协议
没落英雄2 小时前
5. 从零开始搭建一个 AI Agent —— 人机协作与中断恢复
前端·人工智能·架构
品尚公益团队3 小时前
C#在asp.net网页开发中的带cookie登录实现
前端·c#·asp.net
多加点辣也没关系3 小时前
JavaScript|第9章:对象 — 基础
开发语言·javascript·ecmascript
没有了遇见3 小时前
AI Agent 是什么?—— 一文理解 LLM、Memory、Skills、Tools、MCP、Workflow,Context
android·前端·程序员
用户83134859306984 小时前
Cesium自定义可调节星空夜景+星星闪烁
vue.js·cesium
后台开发者Ethan4 小时前
setState组件更新
前端·javascript·react
谙忆10244 小时前
大文件上传实战:前端分片、断点续传、秒传与并发控制怎么落地
前端
轻动琴弦5 小时前
VoltTool —— 一站式在线开发者工具平台,69+实用工具免费使用
前端·chrome
就叫飞六吧5 小时前
不同站点iframe嵌套种cookie、localstorege.set() 关系
前端