1. 尾线效果,很适合做轨迹追踪或者路线动画。
2. 数据使用 ./data/lines.json
3. 处理数据
1 var lineStrings = geojson.map(function (feature) { 2 var coordinates = feature.coordinates; 3 var [from, to] = coordinates; 4 var lnglats = [[parseFloat(from[0]), parseFloat(from[1])], [parseFloat(to[0]), parseFloat(to[1])]] 5 return new maptalks.LineString(lnglats); 6 });
4. 将数据处理为 linetrail 并添加到 图层。
1 var offset = 2000; 2 lineTrails = list.slice(0, offset).map(d => { 3 var line = new LineTrail(d.lineString, { 4 chunkLength: d.len / 100, 5 trail: 5, 6 speed: 1, 7 altitude: 100, 8 }, material, threeLayer) 9 return line; 10 }); 11 var lines = list.slice(0, offset).map(d => { 12 return threeLayer.toLine(d.lineString, {}, lineMaterial); 13 });
5. lineTrail 的自定义扩展类
1 //default values 2 var OPTIONS = { 3 trail: 5, 4 chunkLength: 50, 5 speed: 1, 6 altitude: 0, 7 interactive: false 8 }; 9 10 const MAX_POINTS = 1000; 11 12 /** 13 * custom component 14 * */ 15 16 class LineTrail extends maptalks.BaseObject { 17 constructor(lineString, options, material, layer) { 18 options = maptalks.Util.extend({}, OPTIONS, options, { layer, lineString }); 19 super(); 20 //Initialize internal configuration 21 // https://github.com/maptalks/maptalks.three/blob/1e45f5238f500225ada1deb09b8bab18c1b52cf2/src/BaseObject.js#L135 22 this._initOptions(options); 23 24 const { altitude, chunkLength, speed, trail } = options; 25 const chunkLines = lineSlice(lineString, chunkLength); 26 27 28 const centerPt = layer.coordinateToVector3(lineString.getCenter()); 29 //cache position for faster computing,reduce double counting 30 const positionMap = {}; 31 for (let i = 0, len = chunkLines.length; i < len; i++) { 32 const chunkLine = chunkLines[i]; 33 for (let j = 0, len1 = chunkLine.length; j < len1; j++) { 34 const lnglat = chunkLine[j]; 35 const key = lnglat.join(',').toString(); 36 if (!positionMap[key]) { 37 positionMap[key] = layer.coordinateToVector3(lnglat).sub(centerPt); 38 } 39 } 40 } 41 42 const positions = getChunkLinesPosition([chunkLines[0]], layer, positionMap, centerPt).positions; 43 const geometry = new THREE.BufferGeometry(); 44 const ps = new Float32Array(MAX_POINTS * 3); // 3 vertices per point 45 geometry.addAttribute('position', new THREE.BufferAttribute(ps, 3).setDynamic(true)); 46 setLineGeometryAttribute(geometry, positions); 47 this._createLine(geometry, material); 48 49 //set object3d position 50 const z = layer.distanceToVector3(altitude, altitude).x; 51 52 const center = lineString.getCenter(); 53 const v = layer.coordinateToVector3(center, z); 54 this.getObject3d().position.copy(v); 55 56 this._params = { 57 trail: Math.max(1, trail), 58 index: 0, 59 len: chunkLines.length, 60 chunkLines, 61 layer, 62 speed: Math.min(1, speed), 63 idx: 0, 64 positions: [], 65 positionMap, 66 centerPt 67 }; 68 // this._init(); 69 } 70 71 72 _init() { 73 const { len, chunkLines, layer, trail, positionMap, centerPt } = this._params; 74 for (let i = 0; i < len; i++) { 75 const result = chunkLines.slice(i, i + trail); 76 const ps = getChunkLinesPosition(result, layer, positionMap, centerPt).positions; 77 this._params.positions[i] = ps; 78 } 79 } 80 81 82 _animation() { 83 const { index, positions, idx, speed, len, chunkLines, layer, trail, positionMap, centerPt } = this._params; 84 const i = Math.round(index); 85 if (i > idx) { 86 this._params.idx++; 87 let ps = positions[i]; 88 if (!ps) { 89 const result = chunkLines.slice(i, i + trail); 90 ps = getChunkLinesPosition(result, layer, positionMap, centerPt).positions; 91 this._params.positions[i] = ps; 92 } 93 setLineGeometryAttribute(this.getObject3d().geometry, ps); 94 this.getObject3d().geometry.attributes.position.needsUpdate = true; 95 } 96 if (index >= len) { 97 this._params.index = -1; 98 this._params.idx = -1; 99 } 100 this._params.index += speed; 101 } 102 }
6. 页面效果
7. 源码地址
https://github.com/WhatGIS/maptalkMap/tree/main/threelayer/demo