Skip to content

185. 地图飞线(四)

Published:

上节实现了飞机飞线动画:

2025-08-17 21.49.03.gif

这节加上这个落地点的涟漪动画:

9cb00b3e43736b8c367d8388fbc29fc7.png

其实这个也很简单:

image.png

就是画一圈圈的宽度不一的曲线,然后不断改变 scale 就好了。

我们画一下:

image.png

image.png

在目标位置画一个 5 圈的圆圈,lineWidth 分别是 4、3、2、1、1

drawRipple(new THREE.Vector3(endPos[0], -endPos[1], 0));
function drawRipple(pos) {
    const ripple = new THREE.Group();
    for(let i = 0; i< 5; i++) {
        const arc = new THREE.EllipseCurve(0, 0, i * 5 , i * 5, 0, Math.PI * 2);
        const pointsArr = arc.getPoints(50);
        const geometry = new LineGeometry();
        geometry.setFromPoints(pointsArr);
        const material = new LineMaterial({
            color: new THREE.Color('green'),
            linewidth:  (4 - i <= 0) ? 1 : 4 - i
        });
        const line = new Line2(geometry, material);
        ripple.add(line);
    }
    ripple.position.copy(pos);
    chinaMap.add(ripple);
}

2025-08-17 22.24.50.gif

然后让它动起来,改变 scale:

image.png

ripple.scale.set(0.2,0.2,0);
gsap.to(ripple.scale, {
    y: 1,
    x: 1,
    ease: 'none',
    repeat: -1,
    duration: 2 
});

scale 从 0.2 到 1 变化。

2025-08-17 22.28.55.gif

终点的涟漪动画完成!

再加一个起点的动画:

我们在起点放一个悬浮的倒立圆锥:

image.png

image.png

const geometry = new THREE.ConeGeometry(10, 30);
const material = new THREE.MeshBasicMaterial({color: 'red'});
const cone = new THREE.Mesh(geometry, material);
cone.position.x = startPos[0];
cone.position.y = -startPos[1];
cone.position.z = 20;
cone.rotateX(-Math.PI /2);

chinaMap.add(cone);

画一个红色的圆锥,设置下位置、旋转角度。

2025-08-17 22.43.20.gif

然后让它动起来,上下悬浮运动:

image.png

gsap.to(cone.position, {
    z: 40,
    ease: 'none',
    repeat: -1,
    duration: 2,
    yoyo: true
});

上下反复做 z 的位置的变化。

2025-08-17 22.46.13.gif

改成 1s,然后圆的分段改成 6:

image.png

地图旋转一下:

image.png

chinaMap.rotateX(-Math.PI / 2);

2025-08-17 22.49.03.gif

顺便调一下相机角度:

image.png

看下最终效果:

2025-08-17 22.52.06.gif

案例代码上传了小册仓库

总结

这节我们给地图飞线加上了起点和终点的动画。

终点是画了几个圆圈,做 scale 的动画,实现涟漪效果。

起点画了一个倒立的圆锥,做上下的 position 的动画。

在地图可视化相关的项目里,曲线 api 和 gsap 动画都是很常用的。

评论