3d 地图飞线
代码仓库:
King/threejs-3d-map
核心代码:
import flyLine from "./constant/flyLine.json";const initFlyLine = () => {flyLine.forEach(item => {const [from_x, from_y] = d3Function(item.from)const [to_x, to_y] = d3Function(item.to)const start = new THREE.Vector3(from_x, -from_y, 32); // 起点坐标const v1Point = [item.from[0] + (item.to[0] - item.from[0]) / 4, item.from[1] + (item.to[1] - item.from[1]) / 4]const [v1_x, v1_y] = d3Function(v1Point)const v1 = new THREE.Vector3(v1_x, -v1_y, 100);const v2Point = [item.from[0] + ((item.to[0] - item.from[0]) * 3) / 4, item.from[1] + ((item.to[1] - item.from[1]) * 3) / 4]const [v2_x, v2_y] = d3Function(v2Point)const v2 = new THREE.Vector3(v2_x, -v2_y, 100);const end = new THREE.Vector3(to_x, -to_y, 32); // 终点坐标// 创建三次贝塞尔曲线const curve = new THREE.CubicBezierCurve3(start, v1, v2, end);// 使用 TubeGeometry 根据贝塞尔曲线绘制管道const tubeGeometry = new THREE.TubeGeometry(curve, 256, 2, 8, false); // 曲线256段, 半径2, 20个横截面// 创建材质,颜色为白色const material = new THREE.MeshBasicMaterial({color: item.color});// 创建管道网格const tubeMesh = new THREE.Mesh(tubeGeometry, material);// 将管道添加到场景中showScene.add(tubeMesh);const points = curve.getPoints(1000)const bufferGeometry = createBufferGeometry(points)const shaderMaterial = createShaderMaterial()const point = new THREE.Points(bufferGeometry, shaderMaterial)showScene.add(point)// 设置着色器的动画gsap.fromTo(shaderMaterial.uniforms.uTime,{ value: 0 },{// 实现飞线钻地效果需要让 动画节段数 = 飞线长度 + 飞线点数量value: 80 + 1000,duration: 3,repeat: -1,delay: 0,ease: "none",onUpdate: () => {},});})
}// 创建着色器
function createShaderMaterial() {// 起点颜色let color1 = "#0c57e3";return new THREE.ShaderMaterial({depthTest: false,uniforms: {// 线条颜色uColor: {value: new THREE.Color(color1),},// 时间1-1000uTime: {value: 0,},// 水滴宽度uWidth: {value: 200,},// 水滴长度uLength: {value: 80,},vSize: {value: 10.0},},vertexShader: /*glsl*/ `attribute float aIndex; // 内部属性 浮点 当前序号uniform float uTime; // 全局变量 浮点 当前时间uniform float uWidth; // 全局变量 浮点 线段宽度uniform vec3 uColor; // 全局变量 颜色 设置的颜色varying float vSize; // 片元变量(需要传递到片面着色器) 浮点 尺寸uniform float uLength; // 全局变量 浮点 线段长度void main(){vec4 viewPosition = viewMatrix * modelMatrix * vec4(position,1);gl_Position = projectionMatrix * viewPosition; // 顶点矩阵变换 设置各个点的位置// 当前顶点的位置处于线段长度内 则设置水滴大小if(aIndex >= uTime - uLength && aIndex < uTime){// 水滴大小根据当前位置慢慢变小// p1 uWidth越大水滴越粗// vSize = uWidth * ((aIndex - uTime + uLength) / uLength);// p2 uWidth越大水滴越细vSize = (aIndex + uLength - uTime) / uWidth;}gl_PointSize = vSize;}`,fragmentShader: /*glsl*/ `varying float vSize;uniform vec3 uColor;void main(){// 透明度根据当前大小确定是否展示if(vSize<=0.0){gl_FragColor = vec4(1,0,0,0);}else{gl_FragColor = vec4(uColor,1);}}`,transparent: true,vertexColors: false,});
}// 创建bufferGeometry
function createBufferGeometry(points) {const indexList = points.map((_, index) => index);const bufferGeometry = new BufferGeometry().setFromPoints(points);// 给几何体添加自定义的索引标识 用来后续根据索引设置点的透明度bufferGeometry.setAttribute("aIndex",new THREE.Float32BufferAttribute(indexList, 1));return bufferGeometry;
}
[{"from": [104.065735,30.659462],"to": [116.405285,39.904989],"color": "#00fbff"},{"from": [104.065735,30.659462],"to": [121.472644,31.231706],"color": "#ff0004"},{"from": [104.065735,30.659462],"to": [87.617733,43.792818],"color": "#d8ff94"},{"from": [104.065735,30.659462],"to": [121.509062,25.044332],"color": "#08c9ff"},{"from": [104.065735,30.659462],"to": [112.982279,28.19409],"color": "#ff00ee"}
]
下一篇:
Threejs 实现3D 地图(07)3d 地图 完结-CSDN博客