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

能够参阅下面的作用。

Vue3 完成一个简略的放大动画

规划思路

定位动画咱们在之前现已完成了。那么这儿只需考虑怎么完成放大动画,最终将两者结合起来就好。从后端拿到的返回值是一个固定长度的数组,所以这儿仍是用 div 使用 flex 布局将图片平铺展现,使用 CSS transform 进行位置移动和缩放。

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

Vue3 完成一个简略的放大动画

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

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

inner 移动的偏移量:

// 让 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…

布局部分代码:

  <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>

数据结构部分:

export const imageDemos = [
  {
    name: "image-1",
    src: "https://www.6hu.cc/storage/2024/03/239424-amCNYQ.jpg?1447856922",
    active: false,
  },
  {
    name: "image-2",
    src: "",
    active: false,
  },
  {
    name: "image-3",
    src: "",
    active: false,
  },
  {
    name: "image-4",
    src: "",
    active: false,
  },
  {
    name: "image-5",
    src: "https://gd-hbimg.huaban.com/f0c7a577ed51f171967cbd3c1b21e90361b6924b1594b7-yrOBDd",
    active: false,
  },
];

偏移量计算部分代码:

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 之间的关系了,这又是另一个话题了