旋转时将元素对准圆心 (CSS/JS)

Aim element towards circle centre while rotating (CSS/JS)

我试图以圆周运动移动 10 个物体,同时它们指向圆心

我在 .js 中使用一些三角函数将元素定位在圆上,但是当我尝试围绕圆心旋转它们时,它们旋转不正确,中心看似随机。我正在尝试使用 transformOrigin 属性.

围绕中心旋转它们

如果我 没有为 SeedParent 指定 'initial rotation',那么旋转会按预期工作,但箭头的方向都指向同一个方向(我希望它们都向内指向中心)。我认为这是因为在更改父级的 'initial rotation' 时旋转轴发生了变化。希望代码能更好地解释:

N.B: 原图'Seed'我发不出来,所以用箭头代替。

function AddImageToDiv(Index){
    var Seed = document.createElement("div");
    var SeedParent = document.createElement("div");
    var SpiralDiv = document.getElementById("spiralDiv");
    //The seeds are added to the SpiralDiv
   
    
    Seed.classList.add("seedDiv", "Rotate");
    SeedParent.classList.add("seedParentDiv", "Move")
    
    SpiralDiv.appendChild(SeedParent);
    SeedParent.appendChild(Seed);

    SetSeedPositionAndAngle(Seed, SeedParent, Index)
    //Position the seed on the edge of the circle using index to determine its position


}

function SetSeedPositionAndAngle(Seed, SeedParent, Index){
    var Angle = 2*Math.PI/NumberOfSeeds * Index;

    var PositionOffset = {x: CircleRadius * Math.cos(Angle), y: CircleRadius * Math.sin(Angle)}
  
    SeedParent.style.transform = 
    " translate(" + PositionOffset.x + "px," + PositionOffset.y +"px) rotate(" + (Angle + Math.PI * 0.9) + "rad)";
    //Positioning handled in the parent element
    //If the ROTATE portion is taken out, the rotation works as expected, but the arrows do 
    //not point towards the centre of the circle.
            
    Seed.style.transformOrigin = (-PositionOffset.x + Seed.clientWidth/2) + "px "  +(- PositionOffset.y + Seed.clientWidth/2) + "px";
    //Transform origin set as the coordinate to rotate around

}

const NumberOfSeeds = 10; //The number of elements in the circle
const CircleRadius = 190; //Radius in pixels

for (let index = 1; index < 11; index++) {
    AddImageToDiv(index);
    
}
*{
    margin:0px;
    padding: 0px;
    box-sizing: border-box;
}

:root{
    --greytextcolor: #808080;
}

/* SEED ANIMATION */

.seedDiv {
    display: inline-block;
    position: absolute;
    
    width: 110px;
 background:linear-gradient(45deg,transparent,orange);
    -webkit-mask:url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
          mask:url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;

  }

  .seedDiv::before {
    content:"";
    display:block;
    padding-top:113.6%;

    /* Sets the padding of the top to 113.6% of the padding of the width due to ratio of the image */
 }

 .seedDiv.Rotate{
    animation-name: RotateAroundCenter;
    animation-fill-mode: forwards;
    animation-timing-function: ease-in-out;
    animation-duration: 3s;
    animation-delay: 3s;
/*I've set an animation delay, so you can see the inital positioning of the arrows*/

 }
 
#spiralDiv{
    display: flex;
    justify-content: center;
    position: relative;
    top: 200px;
}

@keyframes RotateAroundCenter{
    100%{
        transform: rotate(-360deg);
        
    }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="stylesheet.css">
    <link href="https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
    
    <script defer src="node_modules/swup/dist/swup.min.js"></script>
    <script defer src='index.js'></script>
    
    <title>Seed Rotate</title>
</head>
<body>

    <main id="swup" class="transition-fade">

        <div id = "spiralDiv">
            
        </div>
    </main>
</body>
</html>

如果有更好的方法,我洗耳恭听:)

我会简化您的代码并依靠 CSS 变量使其变得简单。诀窍是知道如何链接转换。

在下面您会注意到两种旋转,一种将定义箭头的方向(放置在平移之后),另一种将围绕圆旋转元素(放置在平移之前)。您也不需要任何 transform-origin:

function AddImageToDiv(Index) {
  var SeedParent = document.createElement("div");
  var SpiralDiv = document.getElementById("spiralDiv");
  //The seeds are added to the SpiralDiv
  SeedParent.classList.add("seedDiv", "Rotate");

  SpiralDiv.appendChild(SeedParent);

  SetSeedPositionAndAngle(SeedParent, Index)
}

function SetSeedPositionAndAngle(SeedParent, Index) {
  var Angle = 2 * Math.PI / NumberOfSeeds * Index;

  var PositionOffset = {
    x: CircleRadius * Math.cos(Angle),
    y: CircleRadius * Math.sin(Angle)
  }

  SeedParent.style.setProperty("--x", PositionOffset.x + "px");
  SeedParent.style.setProperty("--y", PositionOffset.y + "px");
  SeedParent.style.setProperty("--r", (Angle + Math.PI) + "rad");

}

const NumberOfSeeds = 10; //The number of elements in the circle
const CircleRadius = 190; //Radius in pixels

for (let index = 1; index < 11; index++) {
  AddImageToDiv(index);

}
* {
  margin: 0px;
  padding: 0px;
  box-sizing: border-box;
}
/* SEED ANIMATION */

.seedDiv {
  position: absolute;
  width: 110px;
  background: linear-gradient(45deg, transparent, orange);
  -webkit-mask: url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
  mask: url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
}

.seedDiv::before {
  content: "";
  display: block;
  padding-top: 113.6%;
}

.seedDiv.Rotate {
  animation: RotateAroundCenter 3s 3s ease-in-out forwards;
  transform: rotate(0) translate(var(--x), var(--y)) rotate(var(--r));
}

#spiralDiv {
  display: flex;
  justify-content: center;
  position: relative;
  top: 200px;
}

@keyframes RotateAroundCenter {
  100% {
    transform: rotate(-360deg) translate(var(--x), var(--y)) rotate(var(--r));
  }
}
<div id="spiralDiv">

</div>

如果你以不同的方式进行转换,你可以进一步简化代码

function AddImageToDiv(Index) {
  var SeedParent = document.createElement("div");
  var SpiralDiv = document.getElementById("spiralDiv");
  //The seeds are added to the SpiralDiv
  SeedParent.classList.add("seedDiv");

  SpiralDiv.appendChild(SeedParent);
  
  var Angle = 2 * Math.PI / NumberOfSeeds * Index;
  SeedParent.style.setProperty("--r", (Angle + Math.PI) + "rad");
}

const NumberOfSeeds = 10; //The number of elements in the circle

for (let index = 0; index < NumberOfSeeds; index++) {
  AddImageToDiv(index + 1);
}
/* SEED ANIMATION */
.seedDiv {
  position: absolute;
  width: 110px;
  background: linear-gradient(45deg, transparent, orange);
  -webkit-mask: url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
          mask: url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
  animation: RotateAroundCenter 3s 3s ease-in-out forwards;
  transform: rotate(0)  rotate(var(--r)) translate(-200px);
}

.seedDiv::before {
  content: "";
  display: block;
  padding-top: 113.6%;
}

#spiralDiv {
  display: flex;
  justify-content: center;
  position: relative;
  top: 200px;
}

@keyframes RotateAroundCenter {
  100% {
    transform: rotate(-360deg) rotate(var(--r)) translate(-200px);
  }
}
<div id="spiralDiv"></div>

相关问题以了解为什么顺序在链接转换时很重要:


我们还可以优化最后的代码:

const NumberOfSeeds = 10; //The number of elements in the circle

for (let index = 0; index < NumberOfSeeds; index++) {
  var SeedParent = document.createElement("div");
  var SpiralDiv = document.getElementById("spiralDiv");
  //The seeds are added to the SpiralDiv
  SeedParent.classList.add("seedDiv");

  SpiralDiv.appendChild(SeedParent);
  
  var Angle = 360 / NumberOfSeeds * (index + 1);
  SeedParent.style.setProperty("--r", (Angle + 180) + "deg");
}
/* SEED ANIMATION */
.seedDiv {
  position: absolute;
  width: 110px;
  background: linear-gradient(45deg, transparent, orange);
  -webkit-mask: url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
          mask: url('https://lh3.googleusercontent.com/proxy/5xwQBbe4tsxwqwDthUeiLd_UFRsFEDl3_TT2skCOLzQpgAnKyI5PT9Lfukwjdan6jDQNL0g7qrtupEXM_wQN3VZW') center/contain no-repeat;
  animation: RotateAroundCenter 3s 3s ease-in-out forwards;
  transform: rotate(var(--r)) translate(-200px);
}

.seedDiv::before {
  content: "";
  display: block;
  padding-top: 113.6%;
}

#spiralDiv {
  display: flex;
  justify-content: center;
  position: relative;
  top: 200px;
}

@keyframes RotateAroundCenter {
  100% {
    transform: rotate(calc(var(--r) - 360deg)) translate(-200px);
  }
}
<div id="spiralDiv"></div>