好久没更新,稀土掘金都开始给我发短信了…… 今年 7 月毕业了,开始挨工作的毒打了,这个文章也是从一个需求中抽象出来的 (不过俺大胆猜测这个需求点会被砍掉)
这个方案有一个超级大的缺陷,就是只确定了运动的起始点和终点,运动过程中点走的是直线,其实应该是一个圆弧。
实现效果
(这种不均匀分布的,是不是更有星星的感觉)
用文字描述一下需求:球面上有若干个点,点击一下,这个点就会跑到球正面中心位置,并且球面上的其他点也会做相应的转动。
分析
选择 translate 还是 rotate
CSS 中有两个 transform 类型:
- translate 位移,可以将元素由一个三维空间位置,移动到另一个三维空间位置,注意 CSS 中的 z 轴方向是面向屏幕的方向;
- rotate 旋转,可以将元素相对指定点、指定轴做旋转;
因为我对这两个类型都不是很熟悉,使用 rotate 的话,元素内容也会发生旋转,所以还是选择了比较好用数学“暴力解决”的 translate。如果其实用 rotate 会更简单,也请和我交流。(带带弟弟.jpg)
点是怎么运动的
再把问题数学抽象一点,当球面上有一个关键点,从 A 位置运动到 B 位置时,在 C 位置上的这个点,会运动到什么位置。
这个方案有一个超级大的缺陷,就是只确定了运动的起始点和终点,运动过程中点走的是直线,其实应该是一个圆弧。
球体运动的两个关键点:
- 旋转轴:关键点运动的起始位置 A,结束位置 B 还有球体的球心 O,可以构成一个平面,该平面的法向就是本次旋转的旋转轴,可以通过OA × OB 求得(× 是向量叉乘哦);
- 旋转角度:由于向量 OA 和 OB 都垂直于旋转轴,所以OA 和 OB 之间的夹角,就是所有点绕旋转轴的旋转角度,可以通过OA · OB 求得(· 是向量点乘哦);
知道了旋转轴、旋转角度,就可以使用罗德里格旋转公式算出其他点运动后的坐标啦。
罗德里格旋转公式(百度百科):
矩阵计算
矩阵形式的旋转公式
实现
代码
这次我是在 codesandbox 上跑的,没有 github 地址,直接把所有代码贴上来吧
tips
一些我在实现中踩到的坑:
- 叉乘后需要标准化到长度为 1 的向量,才是旋转平面的法向量,否则所有点会越来越集中;
- translate 里 x 轴方向和 y 轴方向平移距离,需要在 x 轴坐标和 y 轴坐标上减去元素的半径;
- 如果点击较远的点,运动过程中,球形会看起来像椭球形,这是点是沿直线运动的缺陷导致的;