马黑黑 发表于 2023-7-15 12:07

JS:让子元素做圆弧运动

<style>
#mydiv {
        margin: 20px auto 0;
        position: relative;
        width: 740px;
        height: 460px;
        border: 1px solid gray;
}
#ball {
        position: absolute;
        width: 30px;
        height: 30px;
        border-radius: 50%;
        background: lightgreen;
        box-shadow: inset 0 0 18px 0 darkgreen;
}
</style>

<div id="mydiv">
        <div id="ball"></div>
</div>

<script>

let mx = mydiv.offsetWidth / 2,
        my = mydiv.offsetHeight / 2,
        bx = ball.offsetWidth / 2,
        by = ball.offsetHeight / 2
        a = 0
        canMove = true
        aniId = null;

let circle = () => {
        a = a < 360 ? a + 1 : 0;
        let x1 = mx + (mx - bx) * Math.cos(a * Math.PI / 180) - bx,
                y1 = my + (my - by) * Math.sin(a * Math.PI / 180) - by;
        ball.style.cssText += `
                left: ${x1}px;
                top: ${y1}px;
        `;
        canMove ? aniId = requestAnimationFrame(circle) : cancelAnimationFrame(aniId);
}

circle();

mydiv.onclick = () => {
        canMove = !canMove;
        if(canMove) aniId = requestAnimationFrame(circle);
}

</script>

马黑黑 发表于 2023-7-15 12:07

代码
<style>
#mydiv {
        margin: 20px auto 0;
        position: relative;
        width: 740px;
        height: 460px;
        border: 1px solid gray;
}
#ball {
        position: absolute;
        width: 30px;
        height: 30px;
        border-radius: 50%;
        background: lightgreen;
        box-shadow: inset 0 0 18px 0 darkgreen;
}
</style>

<div id="mydiv">
        <div id="ball"></div>
</div>

<script>

let mx = mydiv.offsetWidth / 2,
        my = mydiv.offsetHeight / 2,
        bx = ball.offsetWidth / 2,
        by = ball.offsetHeight / 2
        a = 0
        canMove = true
        aniId = null;

let circle = () => {
        a = a < 360 ? a + 1 : 0;
        let x1 = mx + (mx - bx) * Math.cos(a * Math.PI / 180) - bx,
                y1 = my + (my - by) * Math.sin(a * Math.PI / 180) - by;
        ball.style.cssText += `
                left: ${x1}px;
                top: ${y1}px;
        `;
        canMove ? aniId = requestAnimationFrame(circle) : cancelAnimationFrame(aniId);
}

circle();

mydiv.onclick = () => {
        canMove = !canMove;
        if(canMove) aniId = requestAnimationFrame(circle);
}

</script>

马黑黑 发表于 2023-7-15 12:15

获得元素在圆周上的XY坐标:

x1 = x0 + r * cos(angle * π /180);
y1 = y0 + r * sin(angle * π /180);

转换成 JS:

x1 = x0 + r * Math.cos(angle * Math.PI / 180);
y1 = y0 + r * Math.sin(angle * Math.PI / 180);

其中,x0、y0 为圆心XY坐标,r 为半径;angle 是夹角,分别转换成弧度,再用余弦、正弦函数进行处理。

要让子元素以内切方式运动,需要半径减去子元素的宽/高的一半,总结果再减去子元素宽/高的一半。

马黑黑 发表于 2023-7-15 12:17

设计好 offset-path 路径,也可以使用 CSS 的关键帧动画实现类似功能,而且可以规避过多的编程,效果也更为稳定。

马黑黑 发表于 2023-7-15 12:22

代码中,实现运动的依赖在变量 a,它代表 angle(角度):

a = a < 360 ? a + 1 : 0;

当 a 小于 360 时,a 不断加 1 ,当它超过了 360,则让它变回 0,从头再来。理论上应该变成 1 最好,因为 360 和 0 是重合的,当 a 变为 360度时,它的下一个度数应该 361

芊芊 发表于 2023-7-15 12:45

我就看看

马黑黑 发表于 2023-7-15 12:47

芊芊 发表于 2023-7-15 12:45
我就看看

算法和数钱钱差不多的,难道不想体验一下数钱钱的乐趣?

红影 发表于 2023-7-15 14:28

这并不是一个圆,却可以用圆的公式计算,真奇妙{:4_173:}

东篱闲人 发表于 2023-7-15 14:31

黑黑又玩球了!{:5_112:}

红影 发表于 2023-7-15 14:35

原来是每1°变化的,试了一下5°,转动更快了{:4_173:}

梦油 发表于 2023-7-15 16:03

我想,这个元素一定很实用。

马黑黑 发表于 2023-7-15 16:43

梦油 发表于 2023-7-15 16:03
我想,这个元素一定很实用。

应该都有用

马黑黑 发表于 2023-7-15 16:44

红影 发表于 2023-7-15 14:28
这并不是一个圆,却可以用圆的公式计算,真奇妙

获取x1和y2坐标的半径不同

马黑黑 发表于 2023-7-15 16:45

红影 发表于 2023-7-15 14:35
原来是每1°变化的,试了一下5°,转动更快了

所以,应该根据需要调整步进值

马黑黑 发表于 2023-7-15 16:45

东篱闲人 发表于 2023-7-15 14:31
黑黑又玩球了!

玩玩更快乐

小辣椒 发表于 2023-7-15 16:57

黑黑辛苦,先学习一下,感觉要理解了才可以动手

小辣椒 发表于 2023-7-15 16:58

马黑黑 发表于 2023-7-15 12:15
获得元素在圆周上的XY坐标:

x1 = x0 + r * cos(angle * π /180);


其实这些注解更加应该理解了才可以懂

小辣椒 发表于 2023-7-15 16:59

马黑黑 发表于 2023-7-15 12:17
设计好 offset-path 路径,也可以使用 CSS 的关键帧动画实现类似功能,而且可以规避过多的编程,效果也更为 ...

路径不会设计,小辣椒完蛋了{:4_203:}

马黑黑 发表于 2023-7-15 18:02

小辣椒 发表于 2023-7-15 16:59
路径不会设计,小辣椒完蛋了

设计路径需要一定的数学知识,当然还有懂得语法规范

马黑黑 发表于 2023-7-15 18:02

小辣椒 发表于 2023-7-15 16:58
其实这些注解更加应该理解了才可以懂

数学知识,和三角函数有关
页: [1] 2 3 4 5 6 7
查看完整版本: JS:让子元素做圆弧运动