1. 在飞线的基础上加入移动轨迹,很像飞机飞过的轨迹。这个效果在百度地图里也有。
2. 在 ArcLine 对象中,加入了 speed 参数,在 ArcLine 的类中加入 _animation 动画代码。
3. 添加 Line。
1 function loadRoad(geojsonURL, textureURL) { 2 fetch(geojsonURL).then(function (res) { 3 return res.text(); 4 }).then(function (text) { 5 return JSON.parse(text); 6 }).then(function (geojson) { 7 const texture = new THREE.TextureLoader().load(textureURL); 8 texture.anisotropy = 16; 9 texture.wrapS = THREE.RepeatWrapping; 10 texture.wrapT = THREE.RepeatWrapping; 11 const camera = threeLayer.getCamera(); 12 const material = new MeshLineMaterial({ 13 map: texture, 14 useMap: true, 15 lineWidth: 13, 16 sizeAttenuation: false, 17 transparent: true, 18 near: camera.near, 19 far: camera.far 20 }); 21 const multiLineStrings = maptalks.GeoJSON.toGeometry(geojson); 22 for (const multiLineString of multiLineStrings) { 23 const lines = multiLineString._geometries.filter(lineString => { 24 const len = lineLength(lineString); 25 return len > 800; 26 }).map(lineString => { 27 const len = lineLength(lineString) 28 const line = new ArcLine(lineString, { altitude: 0, height: len / 3, speed: len / 100000 }, material, threeLayer); 29 line.setToolTip(len); 30 return line; 31 }); 32 threeLayer.addMesh(lines); 33 meshes = meshes.concat(lines); 34 } 35 }); 36 }
4. ArcLine 扩展类
1 var OPTIONS = { 2 altitude: 0, 3 speed: 0.01, 4 height: 100 5 }; 6 7 class ArcLine extends maptalks.BaseObject { 8 constructor(lineString, options, material, layer) { 9 super(); 10 options.offset = material.uniforms.offset.value; 11 options.clock = new THREE.Clock(); 12 //geoutil.js getLinePosition 13 options = maptalks.Util.extend({}, OPTIONS, options, { layer, lineString }); 14 this._initOptions(options); 15 16 const { altitude, height } = options; 17 const points = getArcPoints(lineString, layer.distanceToVector3(height, height).x, layer); 18 const geometry = new THREE.Geometry(); 19 geometry.vertices = points; 20 const meshLine = new MeshLine(); 21 meshLine.setGeometry(geometry); 22 23 const map = layer.getMap(); 24 const size = map.getSize(); 25 26 material.uniforms.resolution.value.set(size.width, size.height); 27 28 this._createMesh(meshLine.geometry, material); 29 30 const z = layer.distanceToVector3(altitude, altitude).x; 31 const center = lineString.getCenter(); 32 const v = layer.coordinateToVector3(center, z); 33 this.getObject3d().position.copy(v); 34 this._setPickObject3d(); 35 this._init(); 36 } 37 38 _animation() { 39 this.options.offset.x -= this.options.speed * this.options.clock.getDelta(); 40 } 41 42 _init() { 43 const pick = this.getLayer().getPick(); 44 this.on('add', () => { 45 pick.add(this.pickObject3d); 46 }); 47 this.on('remove', () => { 48 pick.remove(this.pickObject3d); 49 }); 50 } 51 52 53 _setPickObject3d(ps, linewidth) { 54 const geometry = this.getObject3d().geometry.clone(); 55 const pick = this.getLayer().getPick(); 56 const color = pick.getColor(); 57 const { 58 lineWidth, 59 sizeAttenuation, 60 transparent, 61 near, 62 far 63 } = this.getObject3d().material; 64 const material = new MeshLineMaterial({ 65 lineWidth, 66 sizeAttenuation, 67 transparent, 68 near, 69 far, 70 color 71 }); 72 const map = this.getMap(); 73 const size = map.getSize(); 74 75 material.uniforms.resolution.value.set(size.width, size.height); 76 const mesh = new THREE.Mesh(geometry, material); 77 mesh.position.copy(this.getObject3d().position); 78 79 const colorIndex = color.getHex(); 80 mesh._colorIndex = colorIndex; 81 this.setPickObject3d(mesh); 82 } 83 84 identify(coordinate) { 85 return this.picked; 86 } 87 } 88 89 function getArcPoints(lineString, height, layer) { 90 const lnglats = []; 91 if (Array.isArray(lineString)) { 92 lnglats.push(lineString[0], lineString[lineString.length - 1]); 93 } else if (lineString instanceof maptalks.LineString) { 94 const coordinates = lineString.getCoordinates(); 95 lnglats.push(coordinates[0], coordinates[coordinates.length - 1]); 96 } 97 const [first, last] = lnglats; 98 let center; 99 if (Array.isArray(first)) { 100 center = [first[0] / 2 + last[0] / 2, first[1] / 2 + last[1] / 2]; 101 } else if (first instanceof maptalks.Coordinate) { 102 center = [first.x / 2 + last.x / 2, first.y / 2 + last.y / 2]; 103 } 104 const centerPt = layer.coordinateToVector3(lineString.getCenter()); 105 const v = layer.coordinateToVector3(first).sub(centerPt); 106 const v1 = layer.coordinateToVector3(last).sub(centerPt); 107 const vh = layer.coordinateToVector3(center, height).sub(centerPt); 108 const ellipse = new THREE.CatmullRomCurve3([v, vh, v1], false, 'catmullrom'); 109 const points = ellipse.getPoints(40); 110 return points; 111 }
5. 页面显示
6. 源码地址
https://github.com/WhatGIS/maptalkMap/tree/main/threelayer/demo