上节画了北京到上海的飞线:

这节继续把北京到其他城市的飞线画出来:
我们已经拿到每个城市中心点的经纬度了:

遍历画一遍就可以:

起点都是北京,终点是遍历的每个城市的坐标。
const beijingPos = mercator(cityCenterMap.get('北京市'));
for(let [name, center] of cityCenterMap.entries()) {
if(!name) {
continue;
}
if(name === '北京市') {
continue;
}
const endPos = mercator(center);
const start = new THREE.Vector3( beijingPos[0], -beijingPos[1], 0 );
const end = new THREE.Vector3( endPos[0], -endPos[1], 0 );
const middle = start.clone().add(end).divideScalar(2);
middle.z = 100;
const curve = new THREE.CatmullRomCurve3([
start,
middle,
end
]);
const pointsArr = curve.getPoints(20);
const geometry = new LineGeometry();
geometry.setFromPoints(pointsArr);
const material = new LineMaterial({
color: new THREE.Color('orange'),
linewidth: 3
});
const line = new Line2(geometry, material);
chinaMap.add(line);
}
看下效果:

这样曲线是画出来了,但比较丑。
不管远近都是一样的高度,这样肯定是不好的。
我们应该根据两个点的距离来设置高度:

用两个点的 sub 再取 length 来计算距离,设置到 z
顺便把 lineWidth 调小点。
const distance = start.clone().sub(end).length();
middle.z = distance / 3;

这样,离得越近,飞线越低,越远飞线越高。
现在飞线不能标识方向,怎么知道是从北京到其他省市,而不是反过来呢?
所以我们要加一个方向的标识。
先改一下曲线颜色:

曲线取 100 个点。
然后我们从这 100 个点里取一部分画一条不同颜色的曲线。

const pointsArr2 = pointsArr.slice(30, 30 + 20);
const geometry2 = new LineGeometry();
geometry2.setFromPoints(pointsArr2);
const material2 = new LineMaterial({
color: new THREE.Color('orange'),
linewidth: 2
});
const line2 = new Line2(geometry2, material2);
chinaMap.add(line2);
从第 30 个点开始取 20 个点,画一条橙色的线。

然后让它动起来。
怎么动起来呢?
现在是从 30 开始取 20 个点画的线。
下一帧从 40 开始取 20 个点画线,是不是就动起来了?

let index = 30;
function render() {
if(index >= 100) index = 0;
index++;
const arr = pointsArr.slice(index, index + 20);
geometry2.setFromPoints(arr);
requestAnimationFrame(render);
}
render();

有点慢,我们还是用 gsap 来控制:
pnpm install --save gsap

let obj = { index: 0 };
gsap.to(obj, {
index: 100,
ease: 'none',
repeat: -1,
duration: 2,
onUpdate() {
const arr = pointsArr.slice(obj.index, obj.index + 20);
geometry2.setFromPoints(arr);
}
})

现在就是 2s 一次飞线动画了。
我们换一个先加速后减速的缓动动画:

去掉 AxesHelper 看下效果:

这样比匀速好很多,更有方向感。

案例代码上传了小册仓库
总结
这节我们实现了飞线动画。
从曲线上取了一部分的点,又画了一条不同颜色的新的曲线。
然后用 gasp 做动画,不断改变起始点的 index,从原曲线上截取不同的位置的点来画新曲线。
这样就可以实现标识方向的动画。