资讯专栏INFORMATION COLUMN

地图绘制初探——基于maptalks的2.5D地图绘制

qylost / 2921人阅读

摘要:下面,以贵州省的伪地图为例,进行代码的编写和相应数据的简单处理。根据问答如何合并区域边界,访问在线的地图数据处理网站,给每个县市取一个相同的别名,一番输入输出,我们就得到了贵州省的外边界。

进行图形可视化,难免会遇到地理数据的可视化需求。通常情况下,直接使用echarts对配置项进行处理,就可以满足大部分需求。当然,更加复杂的定制化需求,可能就需要借助d3、Three.js等工具。如果对详细的地图背景有要求的话,又需要将图形库与leaflet、maptalks等地图引擎相结合。
不过也许你的需求和我一样,没有那么复杂的交互需求,但对显示效果却有一些想法。那么就可以尝试阅读本文,使用一种比较偷懒的方法,仅基于maptalks本身,来绘制可交互的伪3d地图。
下面,以贵州省的伪3d地图为例,进行代码的编写和相应数据的简单处理。

1.基本的地图绘制
maptalks(maptalks的git)的官方范例写得相当亲切,我们可以从中找到所有绘制伪3d地图需要的元素。
首先,从地图底图开始。(官方入门示例)

initMapTalk() {
  let map = new maptalks.Map("mapDom", {
    center: [121.345, 31.2088],
    zoom: 9,
    baseLayer: new maptalks.TileLayer("base", {
      urlTemplate: "http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png",
      subdomains: ["a","b","c","d"],
      attribution: "© OpenStreetMap contributors, © CARTO"
    })
  });
}

需要注意的是,除了maptalks.js以外,maptalks.css也是必须引入的。

然后,我们需要借助maptalks.Polygon添加一些地图区块(Polygon示例)。虽然地图看起来和长方体不太一样,实际上这些区块也不过是稍微复杂一些的点线集合而已。作为一切绘制的基础,我们需要找一些GeoJson格式的数据(中国各省市级json,世界主要国家json)。观察GeoJson,其中,的coordinates属性,就是地图边界的集合。需要注意的是,区域type包含Polygon和MultiPolygon两类,和maptalks的多边形函数相对应,在数组的层级上稍有区别。为了减少数据选取的麻烦,这里选择使用MultiPolygon来进行绘制。

drawPolygons(idx, coordinates, properties) {
    const polygon = new maptalks.MultiPolygon(coordinates, {
      symbol: {
        lineWidth: 1,
        lineColor: edgeColor,
        polygonFill: polygonColors[0],
        polygonOpacity: 0.5
      },
      properties: {
        id: properties.id,
        index: idx,
        properties: properties
      }
    })
    .on("mouseenter", function(e) {
      e.target.updateSymbol({
        polygonFill: polygonColors[1]
      });
    })
    .on("mouseout", function(e) {
      e.target.updateSymbol({
        polygonFill: polygonColors[0]
      });
    })
    this.polygons.push(polygon);
},
drawRegion() {
    const self = this
    $.getJSON("guizhou.json", "", function(mapData) {
      const features = mapData.features;
      features.forEach((g, i) => {
        const properties = g.properties;
        const coordinates = g.geometry.coordinates
        self.drawPolygons(i, coordinates, properties)
      });
      const polygonsLayer = new maptalks.VectorLayer(
        "vector-polygon",
        self.polygons,
      ).addTo(self.mapDom);
    })
},

到现在为止,一切还只是2d的样子。不过,maptalks允许我们绘制3维的高度面(立体的线)。只需要引入一个altitude属性,并在底图上引入pitch属性使视角稍稍偏移, 我们的2.5d地图就画出来了。

drawLimitLines(idx, coordinates, properties) {
  const outLine = new maptalks.MultiLineString(coordinates, {
    symbol: {
      lineColor: edgeColor,
      lineWidth: 1,
      textPlacement: "vertex"
    },
    properties: {
      altitude: altitude,
      index: idx,
      id: properties.id,
      properties: properties
    }
  });
  this.limitLines.push(outLine);
},
drawPolygons(idx, coordinates, properties) {
  const polygon = new maptalks.MultiPolygon(coordinates, {
    symbol: {
      lineWidth: 1,
      lineColor: edgeColor,
      polygonFill: polygonColors[0],
      polygonOpacity: 0.5
    },
    properties: {
      altitude: altitude,
      id: properties.id,
      index: idx,
      properties: properties
    }
  })
  .on("mouseenter", function(e) {
    e.target.updateSymbol({
      polygonFill: polygonColors[1]
    });
  })
  .on("mouseout", function(e) {
    e.target.updateSymbol({
      polygonFill: polygonColors[0]
    });
  })
  this.polygons.push(polygon);
},
drawRegion() {
  const self = this
  $.getJSON("guizhou.json", "", function(mapData) {
    const features = mapData.features;
    features.forEach((g, i) => {
      const properties = g.properties;
      const coordinates = g.geometry.coordinates
      self.drawPolygons(i, coordinates, properties)
      const pathCoordinates = g.geometry.type == "MultiPolygon" ? coordinates.map(d => { return d[0] }) : coordinates
      self.drawLimitLines(i, pathCoordinates, properties)
    });
    const polygonsLayer = new maptalks.VectorLayer(
      "vector-polygon",
      self.polygons,
      {
        enableAltitude: true
      }
    ).addTo(self.mapDom);
    const limitLinesLayer = new maptalks.VectorLayer(
      "vector-line",
      self.limitLines,
      {
        enableAltitude: true,
        drawAltitude: {
          polygonFill: edgeColor,
          polygonOpacity: 0.3,
          lineWidth: 0
        }
      }
    ).addTo(self.mapDom);
  })
},

2.数据和样式处理
到这个时候,效果还是不太令人满意。县市间的边界太丑,有没有什么办法把他去掉呢?很简单,直接绘制地图的外沿就好。不过,网上下载的贵州省边界好像和现在带有区县划分的精度不太一样?那么,就来自己处理一下吧。根据问答如何合并区域边界,访问在线的地图数据处理网站http://mapshaper.org/,给每个县市取一个相同的别名,一番输入输出,我们就得到了贵州省的外边界。

drawBorderLines(coordinates, properties) {
    const outLine = new maptalks.MultiLineString(coordinates, {
      symbol: {
        lineColor: edgeColor,
        lineWidth: 1,
        textPlacement: "vertex"
      },
      properties: {
        altitude: altitude,
        id: properties.id,
        properties: properties
      }
    });
    this.limitLines.push(outLine);
},
drawWall() {
    const self = this
    $.getJSON("guizhou-border.json", "", function(borderMapData) {
      const borderFeatures = borderMapData.features[0]
      const properties = borderFeatures.properties;
      const pathCoordinates = borderFeatures.geometry.coordinates.map(d => { return d[0] })
      self.drawBorderLines(pathCoordinates, properties)
      const limitLinesLayer = new maptalks.VectorLayer(
        "vector-line",
        self.limitLines,
        {
          enableAltitude: true,
          drawAltitude: {
            polygonFill: edgeColor,
            polygonOpacity: 0.3,
            lineWidth: 0
          }
        }
      ).addTo(self.mapDom);
    })
}

当然,mapshaper的功效不止于此,简直是区域数据处理的一大利器,非常值得探索。
另一个令人不太满意的是地图的底图。打开mapbox,找到Studio然后Start With Basic,一个全新的自配地图的世界等待着你。这里,就随便先把英文的区县名换成中文好了。

完成配置之后,点击share,你会得到一个链接。不过,在用他替换掉Map的urlTemplate之前,还要按照格式进行一下修整。

最后,就得到了本文开头所示的地图。相关源码

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/100333.html

相关文章

  • vue 地图可视化 maptalks

    摘要:首先利用搭建一个项目,然后写一段的。如果对项目的创建比较熟悉,可以跳过步骤一,直接看步骤二。输入保存的模板名字,进入项目初始化构建,等待构建完成。二安装删除,新建,输入如下代码地图初始化,应写在函数中,以保证挂载点先于地图渲染。 Maptalks 项目是一个 HTML5 的地图引擎, 基于原生 ES6 Javascript 开发: 二三维一体化地图, 通过二维地图的旋转 /倾斜增加三维视...

    enali 评论0 收藏0
  • iChart--地图显示人口统计

    摘要:导语大数据呈现应用越来越广泛支持大数据呈现的,水平较高的有然而在地图呈现的功能上,大都只能绘制矢量地图,而不能呈现具有真实效果的地图鉴于此,本文重点在于如何制作一张,即可以看到真实效果,又能进行交互的矢量地图先睹为快若有所思技术选择想实现上 导语 大数据呈现应用越来越广泛,支持大数据呈现的SDK,水平较高的有echarts、highchart、D3;然而在地图呈现的功能上,大都只能绘制...

    mtunique 评论0 收藏0
  • 三、基于lufylegend引擎魔塔游戏开发(绘制第一层地图

    摘要:和代表普通道路和墙,和代表星星和岩浆。用作裁剪接收图片对象起始坐标和裁剪区域五个参数起始坐标和裁剪区域可选用于创建图像,可以添加到游戏图层将指定尺寸按照指定行列进行裁剪,返回一个二维数组生成动画,每一行为一组动画。 绘制地图前准备 在绘制之前,我们先看一下地图的数据实现 globalData = { mapCol: 11, mapRow: 11, size: 32, f...

    Wildcard 评论0 收藏0
  • 入门Leaflet之小Demo

    入门 Leaflet 之小 Demo 写在前面 ---- WebGIS 开发基础之 Leaflet GIS 基本概念:GIS、Map、Layer、Feature、Geometry、Symbol、Data(Point、Polyline、Polygon)、Renderer、Scale、Project、Coordinates; GIS 开发概述:架构模式、常用平台和 SDK、二维三维 使用 Lea...

    Eminjannn 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<