Vue3 实现一个简单的放大动画

这是之前方位动画的衍生需求。先根据后端返回的数据排列内容,然后当用户点击某块内容后居中放大并根据具体的方位数据显示方位动画。

可以参考下面的效果。

设计思路

定位动画我们在之前已经实现了。那么这里只要考虑如何实现放大动画,最后将两者结合起来就好。从后端拿到的返回值是一个固定长度的数组,所以这里还是用 div 利用 flex 布局将图片平铺展示,利用 CSS transform 进行位置移动和缩放。

接下来就是如何计算出每个 div 的位移。DOM 元素的位移主要关注左上角顶点的位移。针对这个需求可以画出如下草图。外层 div 为 container,内层 div 为 inner。

从上图可以看到,每个 div 的位移即 center.left - inner.left, center.top - inner.top. container 的中心点:

javascript 复制代码
const containerCenterX = containerRect.left + containerRect.width / 2;
const containerCenterY = containerRect.top + containerRect.height / 2;

inner 移动的偏移量:

javascript 复制代码
// 让 inner 移到 container 的正中间
const offsetX = containerCenterX - itemRect.width / 2 - itemRect.left;
const offsetY = containerCenterY - itemRect.height / 2 - itemRect.top;

最后将方位动画的 div 叠在 inner 上面即可。

代码实现和 Demo 演示

梳理清思路之后,就可以实现代码了。Demo 已经放在 CodeSandbox 上了。其中最主要的还是位移计算的逻辑。下面是Demo地址,也可以在我的博客上看到 Demo。 Demo 地址:codesandbox.io/p/devbox/si...

布局部分代码:

HTML 复制代码
  <div class="container" ref="container">
    <div
      v-for="(image, index) in imageList"
      :key="index"
      class="wrapper"
      ref="imageElList"
      :style="{ opacity: image.active ? 1 : 0.6 }"
      @click="toggleActiveImage(index)"
    >
      <img :src="image.src" class="image" />
      <direction
        ref="directionElList"
        class="direction"
        :style="{ display: image.active ? 'block' : 'none' }"
        :pinPosition="selectedDirection"
      />
    </div>
  </div>

数据结构部分:

javascript 复制代码
export const imageDemos = [
  {
    name: "image-1",
    src: "https://images.adsttc.com/media/images/564c/8b23/e58e/ce4d/7300/01c1/newsletter/01.jpg?1447856922",
    active: false,
  },
  {
    name: "image-2",
    src: "https://i.pinimg.com/550x/65/a9/10/65a91018534fc59b675150fc432ccc41.jpg",
    active: false,
  },
  {
    name: "image-3",
    src: "https://1.bp.blogspot.com/-PcYuV8FVZmQ/VXWy7y-QjDI/AAAAAAABewE/La-BpNsCsY0/s1600/mapa-grande1.jpg",
    active: false,
  },
  {
    name: "image-4",
    src: "https://image2.sina.com.cn/gm/zhuanqu/sephiroth/rwjs/fomalhaut_b.gif",
    active: false,
  },
  {
    name: "image-5",
    src: "https://gd-hbimg.huaban.com/f0c7a577ed51f171967cbd3c1b21e90361b6924b1594b7-yrOBDd",
    active: false,
  },
];

偏移量计算部分代码:

javascript 复制代码
const showActiveImage = (imageEl) => {
  const containerEl = container.value;

  const containerRect = containerEl!.getBoundingClientRect();
  const itemRect = imageEl!.getBoundingClientRect();

  const containerCenterX = containerRect.left + containerRect.width / 2;
  const containerCenterY = containerRect.top + containerRect.height / 2;

  const offsetX = containerCenterX - itemRect.width / 2 - itemRect.left;
  const offsetY = containerCenterY - itemRect.height / 2 - itemRect.top;

  imageEl!.style.transform = `translate(${offsetX}px, ${offsetY}px) scale(1.2)`;
  imageEl!.style.zIndex = 100;
};

拓展

这次的需求也可以用于展示动画。比如产品展示或者局部细节的展示。根据不同的需求结合不同的动画,可以让我们的页面变得更加酷炫。

题外话

其实这两次的动画效果,代码都是利用 ChatGPT 生成的,我自己基本没有什么参与。在 4 年前我就从前端转到了后端,因此对于前端方面的知识还停留在很久之前。但有了 ChatGPT 的加持,我也可以用当前的前端技术实现一些需求。

尽管这次的需求比较简单,但通过实践可以发现,利用好 AI 能够拓宽我们的技术面,让我们做到更多事情。但于此同时,作为开发者也应当思考与 AI 之间的关系了,这又是另一个话题了

相关推荐
deli00714 分钟前
1 个汉字算几个 token?实测中英文 prompt 与代码的编码差异
前端
无限聚核20 分钟前
抖音 certificate.prepare 之后怎么验券?和美团 msconsume 差在哪,无限聚核
前端·微信小程序
2603_9658966230 分钟前
Grid 网格布局|CSS 二维页面排版体系
前端·css
有味道的男人1 小时前
搜好货平台关键词商品搜索接口:分页容错与商品数据轻量化提取方案
服务器·前端·javascript
lovingsoft1 小时前
Chrome Lighthouse 详解
前端·chrome
Qlly2 小时前
全栈工程师怎么接需求?从一句「加个功能」聊到能开发、能验收
前端·后端
马可家的菠萝2 小时前
你的微信“文件传输助手”,是不是已经成了第二个网盘?
前端·后端·架构
略略略啦2 小时前
Vibe Coding 基于Spec DD和TDD的实践指南
前端
shmily麻瓜小菜鸡2 小时前
前端实现图片与PDF文字识别敏感信息打码方案
前端·pdf·状态模式
打工仔折腾 AI2 小时前
LangChain 工具调用实战:从 Tool 定义到 Agent 执行链路拆解
java·前端·人工智能·后端·python·langchain·ai agent 实战