计算纯 CSS 中的旋转角度

Calculate Angle for Rotation in Pure CSS

我想使用 CSS 动画在整个 window 页面上沿线性路径移动 SVG,并将 SVG 与此路径对齐。参考下图中红线所示的路径,我想指定h为vh的倍数,w为vw的倍数,例如h = 30vh, w = 60vw,并计算旋转 SVG 的角度 α,如蓝色三角形所示。

或者当然,这应该是响应式的并且可以使用不同的 window 尺寸。我希望在纯粹的 CSS.

中完成所有这些

按照 tan(α) = w/h,我可以使用 arcus tangens 函数从商 w/h 计算角度 α。由于三角函数在 CSS yet, I could use a series approximation for calculating the angle as demonstrated here 中不可用。但实际的阻碍似乎是商 w/h 的计算,因为 CSS 中的除法要求分母是无单位的。所以,60vw / 30vh 是不允许的。

在CSS中是否有不同的方法来计算或设置角度?还是我必须退回到这里的 JavaScript 解决方案?

编辑: 这是一个最小的可重现示例。为了在第一个关键帧中设置旋转,需要实际角度 α。它目前固定为 rotate(0deg),因此三角形始终指向上方而不是线性路径的方向。

body {
  overflow: hidden;
}

main {
  color: black;
  background-color: #8dbdff;
}

svg#example {
  position: absolute;
  top: 0%;
  left: 0%;
  transform: translate(-100%, -100%);
  width: 30px;
  height: 30px;
  animation: linear-motion 3.0s linear infinite;
}

@keyframes linear-motion {
  0% {
    transform: translate(0, 30vh) translateX(-100%) rotate(0deg);
  }
  100% {
    transform: translate(60vw, 0vh) translateY(-100%);
  }
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<main class="container-fluid d-flex align-items-center min-vh-100">
  <svg id="example" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100" height="100" viewBox="0 0 100 100">
    <path fill="#008aff" d="M 50,5 95,97.5 5,97.5 z"/>
  </svg>
</main>

根据 A Haworth 的评论,我终于使用 vmin 创建了固定比例的动画。然后可以使用该比率来预先计算角度,如下面的代码片段所示。

此解决方案有一些限制,但响应迅速,适用于不同的 window 尺寸。

body {
  overflow: hidden;
}

main {
  color: black;
  background-color: #8dbdff;
}

svg#example {
  position: absolute;
  top: 0%;
  left: 0%;
  transform: translate(-100%, -100%);
  width: 30px;
  height: 30px;
  animation: linear-motion 3.0s linear infinite;
}

@keyframes linear-motion {
  0% {
    transform: translate(-100%, 40vmin) rotate(66.03deg);
  }
  100% {
    transform: translate(90vmin, -100%) rotate(66.03deg);
  }
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

<main class="container-fluid d-flex align-items-center min-vh-100">
  <svg id="example" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100" height="100" viewBox="0 0 100 100">
    <path fill="#008aff" d="M 50,5 95,97.5 5,97.5 z"/>
  </svg>
</main>