旋转时将元素对准圆心 (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>
我试图以圆周运动移动 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>