Skip to content
目录

实现3D的行政区效果

准备数据

datav 地图小工具 这里下载对应的行政区的geojson数据,自己的项目里的数据从哪里下载还是自己生产的有你的项目决定,这里我只是测试使用,故从datav 地图小工具下载了香港的数据

WARNING

地图数据是个很敏感的东西,尤其是国家的行政边界,项目里使用请遵循对应的法律政策,我这里只是测试使用

创建相关的图层

这里我使用了three插件来实现了3D行政区了,你也可以使用ExtrudePolygonLayer图层

js
// the ThreeLayer to draw buildings
        var threeLayer = new maptalks.ThreeLayer('t', {
            identifyCountOnEvent: 1,
            animation: true
            // forceRenderOnMoving: true,
            // forceRenderOnRotating: true
        });
        threeLayer.prepareToDraw = function (gl, scene, camera) {
            var light = new THREE.DirectionalLight(0xffffff);
            light.position.set(0, -10, 10).normalize();
            scene.add(light);
            scene.add(new THREE.AmbientLight('#fff', 0.3));
            addPolygons();

        };
        // threeLayer.addTo(map);
        // 添加到GroupGLLayer中
        // GroupGLLayer能实现抗锯齿等后处理,也能加入其他三维图层,让子图层都融合到同一个三维空间中
        const sceneConfig = {
            postProcess: {
                enable: true,
                antialias: { enable: true }
            }
        };
        const groupLayer = new maptalks.GroupGLLayer('group', [threeLayer], { sceneConfig });
        groupLayer.addTo(map);

加载数据并构造3D的行政区

  • 关于每个图形的配色,使用了colorin 这个颜色插值库,其也是maptalks里默认使用的颜色插值库
  • 把图形的海拔高度设置为负的目的是不要抬高海平面,方便其他的业务图层数据加到地图,否则会要求其他图层也要设置海拔数据,导致业务逻辑变复杂了,这个样子最简单和不容易出错
js
const colors = [
            [2000, 'lightskyblue'],
            [12000, 'yellow'],
            [30000, 'orangered']
        ];
   const ci = new colorin.ColorIn(colors);
		
   function addPolygons() {
            fetch('../assets/data/hk.json').then(res => res.json()).then(geojson => {
                const polygons = maptalks.GeoJSON.toGeometry(geojson);
                const extrudePolygons = polygons.map(p => {
                    const { value } = p.getProperties();
                    const [r, g, b] = ci.getColor(value);
                    const color = `rgb(${r},${g},${b})`;
                    const extrudePolygon = threeLayer.toExtrudePolygon(p, { height, altitude: -height, topColor: '#fff' }, new THREE.MeshPhongMaterial({ color }));
                    return extrudePolygon;
                });
                threeLayer.addMesh(extrudePolygons);
            })
        }

添加高亮效果

高亮效果即鼠标移动上去,对图形高亮提示,使该图形成为显眼包,这里我们添加图形的mouseover,mouseout事件处理函数,在对应的事件里更新图形的样式即可

  • mouseover 高亮图形
  • mouseout 还原图形原始的样式
js
const highMaterial = new THREE.MeshPhongMaterial({ color: '#fff', vertexColors: 2 });

   function mouseEventFunc(e) {
            const polygon = e.target;
            if (e.type === 'mouseover') {
                if (!polygon._oldSymbol) {
                    polygon._oldSymbol = polygon.getObject3d().material;
                }
                polygon.getObject3d().material = highMaterial;
            } else if (e.type === 'mouseout') {
                if (polygon._oldSymbol) {
                    polygon.getObject3d().material = polygon._oldSymbol;
                }
            }
   }


        function addPolygons() {
            fetch('../assets/data/hk.json').then(res => res.json()).then(geojson => {
                const polygons = maptalks.GeoJSON.toGeometry(geojson);
                const extrudePolygons = polygons.map(p => {
                    const { value } = p.getProperties();
                    const [r, g, b] = ci.getColor(value);
                    const color = `rgb(${r},${g},${b})`;
                    const extrudePolygon = threeLayer.toExtrudePolygon(p, { height, altitude: -height, topColor: '#fff' }, new THREE.MeshPhongMaterial({ color }));
                    extrudePolygon.on('mouseover mouseout', mouseEventFunc);
                    return extrudePolygon;
                });
                threeLayer.addMesh(extrudePolygons);
            })
        }

添加边框线和文字标注

  • 边框线还是使用了图形Polygon,只是把其填充的透明度设置为0而已
  • 文字标注即用点图形,用文字样式系统而已
  • 开启文字碰撞
js
const layer = new maptalks.VectorLayer('layer', {
            // enableAltitude: true
            geometryEvents: false,
            'collision': true,
            'collisionDelay': 250
}).addTo(map);
		
  function addOutLines(polygons) {
            polygons.forEach(polygon => {
                polygon.setSymbol({
                    polygonOpacity: 0,
                    lineWidth: 0.6,
                    lineColor: '#444',
                });
            });
            layer.addGeometry(polygons);
        }

        function addLabels() {
            fetch('../assets/data/hklabel.geojson').then(res => res.json()).then(geojson => {
                const points = maptalks.GeoJSON.toGeometry(geojson);
                points.forEach(point => {
                    const { name } = point.getProperties();
                    point.setSymbol({
                        textName: name,
                        textHaloRadius: 0.2,
                        textHaloFill: '#fff'
                    });

                });
                layer.addGeometry(points);
            })
        }

This document is generated by mdpress