一、three.js地图-绘制多多边形
1. 多多边形
- 数据结构json5观察与多边形的
{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {}, "geometry": { "type": "MultiPolygon", "coordinates": [ [ [ [30.0, 20.0], [45.0, 40.0], [10.0, 40.0], [30.0, 20.0] ] ], [ [ [15.0, 5.0], [40.0, 10.0], [10.0, 20.0], [5.0, 10.0], [15.0, 5.0] ] ] ] } } ] }
genjson
结构就会发现,多多边形coordinates
节点下是多个数组 - 在
geojson.io
上显示
2. 绘制多多边形
多多边形绘制,根据其数据节点,需要改造的代码地方,地图数据解析 和 绘制模块
地图数据解析 和 模块绘制
js/** * 处理地图经纬度数据 */ initMultiplePoly() { this.#mapData?.features?.map(item => { const areas = item.geometry.coordinates; areas.map(area => { const areaVector = { coordinates: [] }; area.map((point, index) => { if (Array.isArray(point[0])) { areaVector.coordinates[index] = []; point?.map(pointInner => { areaVector.coordinates[index].push(this.lnglatToVector(pointInner)) }) } this.#vector3Json.push(areaVector) }) }) }) // 绘制模块 const group = new Group(); this.#vector3Json.map(vectors => { vectors.coordinates.map(vector => { const mesh = this.drawMultiPolyon(vector); group.add(mesh); }) }) this.scene.add(group); }
3. 完整示例
代码示例
jsimport ThreeBase from "./ThreeBase"; import * as D3 from 'd3-geo'; import axios from "axios"; import { Group, Shape, ExtrudeGeometry, MeshBasicMaterial, Mesh } from 'three'; /** * 绘制多多边形 */ export default class ThreeMultiplePolygonMap extends ThreeBase { #projection; #mapData; #vector3Json = []; constructor() { super(); } initObj() { this.initMapData().then(() => { this.initMultiplePoly() }) } initMapData() { return axios.get('geojson/multi-polygon.json').then(res => { this.#mapData = res.data; }) } /** * 绘制网格 */ drawMultiPolyon(points= []) { const shape = new Shape(); points.map((point, index) => { const [x, y] = point; if (index === 0) { shape.moveTo(x, y); } else if (index === points.length - 1) { // 二次曲线 shape.quadraticCurveTo(x, y, x, y) } else { shape.lineTo(x, y, x, y) } }) // bevelEnabled 是否启用斜角 const geometry = new ExtrudeGeometry( shape, { depth: -2, bevelEnabled: false } ) // 材质 const material = new MeshBasicMaterial({ color: "#007cff", transparent: true, opacity: 0.5 }); // 合并 const mesh = new Mesh(geometry, material); return mesh; } /** * 处理地图经纬度数据 */ initMultiplePoly() { this.#mapData?.features?.map(item => { const areas = item.geometry.coordinates; areas.map(area => { const areaVector = { coordinates: [] }; area.map((point, index) => { if (Array.isArray(point[0])) { areaVector.coordinates[index] = []; point?.map(pointInner => { areaVector.coordinates[index].push(this.lnglatToVector(pointInner)) }) } this.#vector3Json.push(areaVector) }) }) }) // 绘制模块 const group = new Group(); this.#vector3Json.map(vectors => { vectors.coordinates.map(vector => { const mesh = this.drawMultiPolyon(vector); group.add(mesh); }) }) this.scene.add(group); } lnglatToVector(lnglat) { if (!this.#projection) { this.#projection = D3.geoMercator() .center([112.946332, 28.236672]) .scale(80) .translate([0,0]); } const [y, x] = this.#projection([...lnglat]); const z = 0; return [y, x, z]; } }
效果展示