首页 > 解决方案 > 如何在 Anime.js 中按照 SVG 路径“完美”居中对象?

问题描述

我正在使用Anime.js围绕SVG 中的圆形路径移动一个 20 像素的正方形。然而,正方形在它的圆形路径中并不完全居中:

在此处输入图像描述

anime({
    targets: '.square',
    translateX: path('x'),
    translateY: path('y'),
    rotate: path('angle'),
    easing: 'linear',
    duration: 10000,
    loop: true,
});

https://codepen.io/gremo/pen/wvKjrMW

我找到了类似的例子,但我无法理解进行这项工作的数学原理:

标签: javascriptcsssvganime.js

解决方案


发生这种情况是因为您的对象(正方形)确实在遵循路径。但是,对象是根据左上角的第一个像素值平移的(因此,如果您制作一个1px x 1px正方形,您应该会看到该正方形很好地跟随路径)。这就是为什么对象的左上角总是粘在这条线上的原因。您想要的是使对象的中间部分粘在线条上。

使用静态和手动计算的值(框的原始宽度和高度的 50%)是合理的(例如-10px,同时给出topleft)。但是,当有许多对象被动画化时,您可能不想这样做(因为您需要在发生更改时更新所有 CSS 代码)。::after相反,我们可以使用你的伪元素.square并将其向左平移 50% 的宽度,向顶部平移 50% 的高度。这样,物体的附着在直线上的点就是正方形的中心部分。现在,当您更新原始.square元素的宽度和高度时,您不需要更新topandleft值。您不能简单地将transform: translate(-50%, -50%)值添加到原始值.squarediv 因为它将使用 Anime.js 进行动画处理,并且初始变换值将丢失。从 JS 获取计算出的初始变换值很棘手。

document.addEventListener('DOMContentLoaded', function() {
  const path = anime.path('.circle path');

  anime({
    targets: '.square',
    translateX: path('x'),
    translateY: path('y'),
    easing: 'linear',
    duration: 10000,
    loop: true,
  });
});
body {
  background-color: #001f3f;
}

.container {
  position: relative;
  margin: 0 auto;
  max-width: 500px;
}

.circle {
  fill: none;
  stroke: #b10dc9;
}

.square {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-block;
  width: 20px;
  height: 20px;
}

.square::after {
  content: '';
  position: absolute;
  width: 100%;
  height: 100%;
  transform: translate(-50%, -50%);
  background-color: #f012be;
}
<script src="https://unpkg.com/animejs@3.2.0/lib/anime.min.js"></script>
<div class="container">
  <svg class="circle" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500">
    <path d="M400,250c0,82.84-67.16,150-150,150s-150-67.16-150-150s67.16-150,150-150S400,167.16,400,250z" />
  </svg>
  <span class="square"></span>
</div>


推荐阅读