css+div+js 实现元素沿 圆/椭圆 轨迹运动
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实现元素沿 圆/椭圆 轨迹运动</title>
<style>
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.circle {
position: relative;
width: 400px;
height: 300px;
border: 1px solid red;
border-radius: 50%;
}
.dot {
position: absolute;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
border: 1px solid red;
border-radius: 50%;
}
</style>
</head>
<body>
<div class="circle">
</div>
<script>
function getPointOnCircle(angle, radius, centerX = 0, centerY = 0) {
const radians = angle * Math.PI / 180
return {
x: centerX + radius * Math.cos(radians),
y: centerY + radius * Math.sin(radians)
}
}
function getPointOnEllipse(a, b, angle, centerX = 0, centerY = 0) {
const radians = angle * Math.PI / 180
const x = centerX + a * Math.cos(radians)
const y = centerY + b * Math.sin(radians)
return { x, y }
}
let itemDom = []
let staticDom = []
let data = {}
function toAnimate() {
let last = itemDom.slice(-1)[0]
if (last) {
data.deg = last.deg
data.startDeg = last.startDeg
data.transform = last.style.transform
data.index = parseInt(last.innerText)
}
let step = 0.5
let count = 36
function animate() {
itemDom.forEach(dom => {
let { x, y } = getPointOnEllipse(200, 150, dom.deg, 180, 130)
dom.style.transform = `translate(${x}px,${y}px)`
dom.deg += step
if (dom.deg > 360) {
dom.deg = 0
}
})
count -= step
if (count <= 0) {
let dom = itemDom.shift()
circleDom.removeChild(dom)
staticDom.push(dom)
if ((staticDom.length + itemDom.length) < 12) {
let dotDom = document.createElement('div')
dotDom.classList.add('dot')
dotDom.innerText = parseInt(data.index) + 1
dotDom.deg = data.deg
dotDom.startDeg = data.startDeg
dotDom.style.transform = data.transform
itemDom.push(dotDom)
circleDom.append(dotDom)
} else {
let dotDom = staticDom.shift()
dotDom.deg = data.deg
dotDom.startDeg = data.startDeg
dotDom.style.transform = data.transform
itemDom.push(dotDom)
circleDom.append(dotDom)
}
setTimeout(() => {
toAnimate()
}, 3000 )
} else {
window.requestAnimationFrame(animate)
}
}
window.requestAnimationFrame(animate)
}
let circleDom = document.querySelector('.circle')
function generate(itemCount) {
let fullCount = 5
let start = -215.5
for (let i = 0; i < fullCount; i++) {
let dotDom = document.createElement('div')
dotDom.classList.add('dot')
dotDom.innerText = i
let { x, y } = getPointOnEllipse(200, 150, start, 180, 130)
dotDom.deg = start
dotDom.startDeg = start
dotDom.style.transform = `translate(${x}px,${y}px)`
itemDom.push(dotDom)
circleDom.append(dotDom)
start -= 36
if (start < -360) {
start = start - -360
}
}
}
generate(12)
toAnimate()
</script>
</body>
</html>
