0


vue3 + MapTalks实现2.5D地图的绘制

一.准备工作

1.npm引入maptalks

我的maptalks版本: "maptalks": "^1.0.0-rc.33",

2.寻找省份的GeoJson数据,选择想要的省份直接下载即可 :阿里DataV地图数据平台

3.在vue单页面中引入maptalks/maptalks.css/省份的GoJson数据
import 'maptalks/dist/maptalks.css';
import * as maptalks from 'maptalks';
import { ref, onMounted } from 'vue';
import tianjinGeoJSON from '@/assets/js/tj.json'; // 导入 GeoJSON 天津市数据

二、基本地图的绘制:根据官网案例实现平面地图

使用官网案例即可:

maptalks官网

<div ref="mapElement" class="map"></div>

// 地图dom元素
const mapElement = ref(null);
// mapInstance 用来引用 MapTalks 的地图实例
const mapInstance = ref(null);

onMounted(() => {
    initMap();
});

const initMap = () => {
    if (mapElement.value) {
        const url = 'https://api.mapbox.com/styles/v1/ling13/cjpv0upr10vc52sodrbmtrmrb/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1IjoibGluZzEzIiwiYSI6ImNqbHozcGRwZDBzMHIzcXBqNXV2dGR4dHAifQ.32-e7GIttC0FriVwvJ0GqA#6.1/27.044989/106.588086/0';
        mapInstance.value = new maptalks.Map(mapElement.value, {
            center: [117.4, 39.4], // 天津中心的经纬度
            zoom: 9,
              pitch: 45, // 设置倾斜角度为45度,实现2.5D效果    
            resizeEnable: true, // 开启resize功能      
            attribution: false,     // 关闭图例    
            zoomControl: false,     // 关闭缩放控件     
            scaleControl: false,     // 关闭比例尺控件
            overviewControl: false,        // 关闭 overview 控件
            baseLayer: new maptalks.TileLayer('base', {
                urlTemplate: url,
                subdomains: ['a', 'b', 'c', 'd'],
                attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>', // 地图数据的归属说明
                cssFilter: 'sepia(100%) invert(90%)'
            }),
        });
    } else {
        console.error('mapElement is null or undefined');
    }
}

设置完中心点击后,地图就开启了(剩余风格自行探索,本期专耕2.5D效果,其余一笔带过)

三、2.5D绘制实现思路

所以如图所示,我们只要绘制一个盖住省份的平面,也就是红色的线+黄色的面,和一个有高度的绿色墙面,拆分着看,问题就迎刃而解了

四、具体代码

1.初始化常量
// 常量和初始数据
const edgeColor = '#4682B4'; // 多边形和线条的边缘颜色
const polygonColors = ["#C0C0C0", "#87CEFA"]; // 多边形填充颜色(默认和悬停)
const altitude = 15000; // 显示在地图上的高度
const polygons = ref([]);// 存储多边形对象的数组
const limitLines = ref([]); // 存储线条对象的数组
2.绘制多边形线

altitude是面的高度配置

使用

maptalks.MultiPolygon

创建多边形对象,传入

coordinates

和配置对象。(传入的对象在下方函数,因为JavaScript引擎宏任务,故此函数需要提升顺序在绘制面函数之前)

将绘制好的多边形对象

polygon

添加到

polygons.value

数组中,用于后续添加到地图图层。

const drawPolygons = (idx, coordinates, properties) => {
    const polygon = new maptalks.MultiPolygon(coordinates, {
        // 边线配置
        symbol: {
            lineWidth: 1,
            lineColor: edgeColor,  // 多边形边线颜色,通过常量 edgeColor 定义
            polygonFill: polygonColors[1], // 默认填充颜色,通过常量 polygonColors 定义
            polygonOpacity: 0.7 // 多边形的透明度
        },
        // 2.5D效果
        properties: {
            altitude: altitude, // 设置多边形的高度(2.5D效果)
            id: properties.id, // 多边形的标识符
            index: idx, // 多边形在数组中的索引
            properties: properties // 多边形的其他属性
        }
    })

    polygons.value.push(polygon); // 将多边形对象添加到 polygons 数组中
}

3.绘制多边形区域的方法

  • forEach 遍历每个 GeoJSON 数据中的多边形,调用 drawPolygons 函数绘制每个多边形。
  • 创建一个 maptalks.VectorLayer 矢量图层,将绘制好的多边形对象数组 polygons.value 添加到图层中。
  • 将矢量图层 polygonsLayer 添加到地图实例 mapInstance.value 中,以显示在地图上。
const drawRegion = () => {
    let MapData = tianjinGeoJSON.features; // 获取天津的GeoJSON数据
    polygons.value = []; // 清空 polygons 数组

    // 遍历 GeoJSON 数据中的每个多边形
    MapData.forEach((g, i) => {
        const properties = g.properties;
        const coordinates = g.geometry.coordinates;
        drawPolygons(i, coordinates, properties); // 绘制每个多边形
    });

    // 创建一个 MapTalks 矢量图层来展示多边形,并添加到地图中(让天津高亮)
    const polygonsLayer = new maptalks.VectorLayer(
        "vector-polygon",  // 图层的名称
        polygons.value,   // 添加的多边形对象数组
        { enableAltitude: true }  // 开启高度效果,必须开启以支持2.5D效果
    );
    mapInstance.value.addLayer(polygonsLayer); // 将图层添加到地图实例中
}
3.红色的线+黄色的面绘制完成,看效果
onMounted(() => {
    initMap();
    drawRegion();//调用绘制区域函数
});

效果不错,继续继续!

4.接下来绘制绿色的墙面

绘制墙体,首先要有边界线然后再给上面一个高度,!

那么开始画边界线:

  • drawBorderLines 函数用于创建一个多段线对象 (MultiLineString),表示地图上的边界线或墙体。
  • 使用 maptalks.MultiLineString 构造函数创建多段线对象,传入 coordinates 和配置对象。
  • 设置线条的样式,包括颜色、宽度以及文本的放置方式。
  • 使用 properties 对象存储线条的额外信息,例如高度、标识符等。
  • 将创建好的线条对象 outLine 添加到 limitLines.value 数组中,以便稍后添加到地图的图层中。
const drawBorderLines = (coordinates, properties) => {
    const outLine = new maptalks.MultiLineString(coordinates, {
        symbol: {
            lineColor: '#5EAEEE', // 线条颜色
            lineWidth: 1, // 线条宽度
            textPlacement: "vertex" // 文本放置方式
        },
        properties: {
            altitude: altitude, // 高度属性(用于2.5D效果)
            id: properties.id, // 边界线的标识符
            properties: properties // 边界线的其他属性
        }
    });
    limitLines.value.push(outLine); // 将线条对象添加到 limitLines 数组中
}

接下来和绘制面一样:

  • drawWall 函数用于绘制边界线或墙体,基于从 tianjinGeoJSON 中获取的地理数据。
  • 遍历 borderFeatures 数组中的每个 feature,每个 feature 通常代表一个边界或墙体。
  • 对每个 feature,从其 geometry.coordinates 中提取路径坐标,然后调用 drawBorderLines 函数绘制边界线。
  • 创建一个 maptalks.VectorLayer 矢量图层 (limitLinesLayer),将存储在 limitLines.value 中的线条对象数组添加到图层中。
  • 配置图层的 drawAltitude 选项,包括填充颜色、透明度和线条宽度等。
  • 最后,将创建好的图层 limitLinesLayer 添加到地图实例 mapInstance.value 中,以在地图上显示绘制的边界线或墙体。
const drawWall = () => {
    limitLines.value = []; // 清空 limitLines 数组

    // 获取包含边界线坐标和属性的 JSON 数据
    const borderFeatures = tianjinGeoJSON.features;

    // 遍历每个 feature,这里假设每个 feature 都代表一个边界
    borderFeatures.forEach(feature => {
        const properties = feature.properties;

        // 从 JSON 数据中提取路径坐标
        const pathCoordinates = feature.geometry.coordinates.map(d => { return d[0] });

        drawBorderLines(pathCoordinates, properties); // 调用绘制边界线的函数
    });

    // 创建一个 MapTalks 矢量图层来展示线条,并添加到地图中
    const limitLinesLayer = new maptalks.VectorLayer(
        "vector-line",
        limitLines.value,
        {
            enableAltitude: true, // 启用高度效果,用于2.5D效果
            drawAltitude: {
                polygonFill: 'edgeColor', // 设置正确的填充颜色,比如橙色
                polygonOpacity: 0.3,
                lineWidth: 0
            }
        }
    );
    mapInstance.value.addLayer(limitLinesLayer); // 将图层添加到地图实例中
}
完成,看效果:
只显示省外边界:

1.合并地图边界:
https://juejin.cn/post/7140454398634754055
2.合并网站:
https://mapshaper.org/

标签: web vue javascript

本文转载自: https://blog.csdn.net/weixin_64908228/article/details/140185174
版权归原作者 herry xiao 所有, 如有侵权,请联系我们删除。

“vue3 + MapTalks实现2.5D地图的绘制”的评论:

还没有评论