maptalks 开发手册-入门篇

为何使用maptalks

做过地图的小伙伴们都知道,每个地图框架产商都与自家的地图资源进行绑定,如非常受欢迎的mapBox、高德、百度、腾讯等,你必须注册他们产品,获取key,然后调用的api,才能进行地图的相关操作,虽然带来了便利, 但同时这也存在这限制。

那么有人可能要问,那这么方便,就用他们的,就不用自己开发了不是,为什么还用其他的呢?

这个问题很好,做产品,最好的做法就是由开发自己掌控,能做什么,能做到什么程度,一切都由开发把握,这才是一个完好的自主产品。说到自主,作为中国人也是有亲身体会的,作物基因专利、光刻机、软件等等,由外国掌控核心技术,作为使用者的我们只能认栽吃瘪,maptalks是我们国人开源的一个地图框架,可以自定义我们的地图资源,不用第三方支持,而且也集成了很多插件,想three、echarts、热力图,支持我们的开发需求。这不是宣传,我就我个人的一些观点。

API

https://maptalks.org/maptalks.js/api/0.x/Map.html

初始化

首先需要安装maptalks

npm install maptalks

和其他框架的差不多,了解就行;
哦,还有一个点,出现跨域的问题,需要设置crossOrigin: undefined

<template>
  <div id="map" class="container"></div>
</template>

<script>
// 引入样式和组件
import 'maptalks/dist/maptalks.css';
import * as maptalks from 'maptalks';

export default {
    
    
  data() {
    
    
    return {
    
    
      // 地图引擎
      mapEngine: null,
      // 倾斜度
      pitch: 50,
      // toolbar
      // 旋转
      whirl: null,
      // 放大/缩小
      zoom: 14,
      // 轴承
      bearing: 0,
      // 屏幕坐标
      containerPoint: {
    
    x: null, y: null},
      // 地图坐标
      coordinatePoint: {
    
    x: null, y: null}
    }
  },
  mounted() {
    
    
    const _t = this
    this.$nextTick(() => {
    
    
      const map = new maptalks.Map('map', {
    
    
        // 默认中心点点位
        center: [118.13245430046891, 24.495713873147764],
        // 缩放层级
        zoom: _t.zoom,
        // 倾斜度
        pitch: _t.pitch,
        // 最小缩放层级
        minZoom: 1,
        // 最大缩放层级
        maxZoom: 18,
        // baseLayer 表示基础图层,它可以添加多个,逗号隔开
        baseLayer: new maptalks.TileLayer('base', {
    
    
          // 出现跨域问题,要设置这个,一定是undefined
          crossOrigin: undefined,
          // 电子地图图层
          urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
          subdomains: ['a', 'b', 'c', 'd'],
          attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
        })
      });
    });

  }
}
</script>

<style lang="scss">
.container {
    
    
  width: 100%;
  height: 100%
}
</style>

Symbol 属性

这个属性是用来设置样式的,是它的一个规则,之后我们的用的功能都与这个有关系,所以这里提前的了解,下面是它的文档说明:

https://github.com/maptalks/maptalks.js/wiki/Symbol-Reference

创建图层

创建图层的方式有两种:

  1. 在创建地图实例的同时创建图层:
    2个参数,必填参数为第一个(id),第二个参数是options,是它的图层属性设置,一般默认就行,后面也可以通过图层对象进行设置。
 const map = new maptalks.Map('map', {
    
    
        // 默认中心点点位
        center: [118.13245430046891, 24.495713873147764],
        // 缩放层级
        zoom: _t.zoom,
        // 倾斜度
        pitch: _t.pitch,
        // 最小缩放层级
        minZoom: 1,
        // 最大缩放层级
        maxZoom: 18,
        // baseLayer 表示基础图层,它可以添加多个,逗号隔开
        baseLayer: new maptalks.TileLayer('base', {
    
    
          // 电子地图图层
          urlTemplate: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png',
          subdomains: ['a', 'b', 'c', 'd'],
          attribution: '&copy; <a href="http://osm.org">OpenStreetMap</a> contributors, &copy; <a href="https://carto.com/">CARTO</a>'
        }),
        layers: [
          // 创建矢量图层 v
          // new maptalks.VectorLayer('v', 几何图形列表(geometries), 可选参数配置(options))
          new maptalks.VectorLayer('v')
        ]
      });
  1. 创建图层实例,然后添加到map实例中
    注意:这里用了一个方法addTo(map)这个方法对所有组件通用,意思就是,下面我们介绍的工具、组件等添加到地图上,都是用这个方法。
new maptalks.VectorLayer('v').addTo(map)

放大缩小等工具

在地图初始化时,我们也可以添加一些我们的工具:

它提供了new maptalks.control.Toolbar让我们去实例一个工具栏,格式:

// 工具栏实例化
      new maptalks.control.Toolbar({
    
    
        items: [
          {
    
    
              // 显示名称
            item: '放大',
              // 点击时间
            click: () => {
    
    
              map.setZoom(_t.zoom += 1)
            }
          }
        ]
      }).addTo(map);

这里我简单了列了items里的属性,它其实共有4个属性:position、vertical、reverseMenu、items,详细可以去看:Maptalks/docs/api/0.x/control.Toolbar.html,也可以从源码角度去看,在源码里它是有默认配置的,比如下面这个:

var options$s = {
    
    
  'height': 28,
  'vertical': false,
  'position': 'top-right',
  'reverseMenu': false,
  'items': {
    
    }
};

缩放工具它有提供现成的组件:

  /**
     * 增加缩放工具
     * @param map
     */
    addZoomTool(map) {
    
    
      new maptalks.control.Zoom({
    
    
        // 工具位置
        position: 'top-left',
        // 是否是以线段条方式展示
        slider: false,
        // 是否显示缩放级别文本框
        zoomLevel: true
      }).addTo(map);
    },

我们也可以自定义创建:

 new maptalks.control.Toolbar({
    
    
        items: [
          {
    
    
            item: '放大',
            click: () => {
    
    
              map.setZoom(_t.zoom += 1)
            }
          },
          {
    
    
            item: '缩小',
            click: () => {
    
    
              map.setZoom(_t.zoom -= 1)
            }
          },
          {
    
    
            item: '旋转',
            click: () => {
    
    
              map.setBearing(_t.bearing -= 50)
            }
          },
          {
    
    
            item: '重置',
            click: () => {
    
    
              _t.mapDataReset(map)
            }
          },
          {
    
    
            item: '锁定',
            click: (t) => {
    
    
              if (t.target.item === '锁定') {
    
    
                map.setOptions({
    
    
                  // 可拖动
                  draggable: false,
                  // 平移
                  dragPan: false,
                  // 旋转
                  dragRotate: false,
                  // 间距
                  dragPitch: false,
                  // 滚动缩放
                  scrollWheelZoom: false,
                  // 点击 缩放
                  touchZoom: false,
                  // 双击缩放
                  doubleClickZoom: false
                })
                t.target.item = '取消锁定'
              } else {
    
    
                map.setOptions({
    
    
                  // 可拖动
                  draggable: true,
                  // 平移
                  dragPan: true,
                  // 旋转
                  dragRotate: true,
                  // 间距
                  dragPitch: true,
                  // 滚动缩放
                  scrollWheelZoom: true,
                  // 点击 缩放
                  touchZoom: true,
                  // 双击缩放
                  doubleClickZoom: true
                })
                t.target.item = '锁定'
              }
            }
          }
        ]
      }).addTo(map);

效果如下:

image-20211023122104588

绘制区域面(几何图形)

首先我们要知道它有2个概念:Geometry  Polygon,polygon继承Geometry,两个可以看做一个东西;

并且,绘制面需要VectorLayer图层上进行绘制。

它画面的原理是,两点定义一条直线,多个点连成多条线,近大远小,远看就是曲线,那么面就是连接了开始和结束的点,使之闭环,加上颜色就是一个面。

好,下载可以找一个数据来测试一下:地图选择器 (aliyun.com)

上面下载一个geojson的数据,名称随便,这里就说一下怎么用它的方法:

​ 首先要清除怎么添加几何面,使用layer.addGeometry(geometry),addGeometry支持单个,也支持数组,那么就是说,我们可以传入的参数可以是:Polygon、MultiPolygon、Geometry、MultiGeometry,或者他们数组。

  1. Polygon

    const optiosn = {
          
          
        visible: true,
        editable: true,
        cursor: 'pointer',
        shadowBlur: 0,
        // 阴影
        shadowColor: 'red',
        draggable: false,
        dragShadow: true,
        drawOnAxis: null,
        enableAltitude: true,
        symbol: {
          
          
            // 线色
            lineColor: '#34495e',
            // 线宽
            lineWidth: 1,
            // 填充色
            polygonFill: 'rgb(135,196,240)',
            // 不透明度
            polygonOpacity: 0.2
        }
    }
    const polygon = new maptalks.Polygon(data, options)
    
    
    new maptalks.VectorLayer('v').addGeometry(polygon).addTo(_t.mapEngine)
    
    

    这种方式比较底层的感觉,因为它传入的数据data是坐标集合,格式如下:

    有3层包裹,真心难受,而且,我们的数据一般都是通过GeoJSON获取的,那么要使用这个方法,我们就得从JSON对象中获取,我一开始,就是使用的这个方法,比较难受。

     [
         [
             [121.55074604278596, 31.242008515751614],
             [121.55074604278596, 31.23914637638951],
             [121.55349262481711, 31.23914637638951],
             [121.55349262481711, 31.24134802974913],
             [121.5518618417361, 31.241384723537074],
             [121.55074604278596, 31.242008515751614]
         ]
     ]
    
    1. MultiPolygon

      maptalks有提供一个GeoJSON的工具类,可以更好的兼容geoJson,这个工具就叫GeoJSON

const geoJson = require( '@/mock/xiamen.json')


  /**
    * 根据geojson画区域面
    * @param geoJson geoJson数据
    * @param layer 需要话的图层
    */
drawAreaPolygon(geoJson, layer) {
    
    
    const _t = this
    const geometry = maptalks.GeoJSON.toGeometry(geoJson)
    if (geometry) {
    
    
        geometry.forEach(g => {
    
    
            g.setSymbol({
    
    
                // 线色
                lineColor: '#34495e',
                // 线宽
                lineWidth: 1,
                // 填充色
                polygonFill: 'rgb(135,196,240)',
                // 不透明度
                polygonOpacity: 0.2
            })
        })
    }
    layer.addGeometry(geometry)
},

maptalks.GeoJSON.toGeometry(geoJson) 获取到的是一个MultiPolygon数组对象

效果如下:

好像这个JSON的数据不是很准确,这个不重要,重要的是我们已经将面画出来了,还需要一些交互。

image-20211023123531130

面的交互(事件监听)

上面我们画出了面,但是只能看,而且没有任何交互,用户体验非常非常的,额…是没有用户体验,现在我们来加一下事件,实现鼠标移动、点击等的交互。

Geometry Polygon 提供了监听事件on和js的一样,这个没什么好说的,下面我就以geoJson创建的面为例:

 drawAreaPolygon(geoJson, layer) {
    
    
        const _t = this
        const geometry = maptalks.GeoJSON.toGeometry(geoJson)
          if (geometry) {
    
    
              geometry.forEach(g => {
    
    
                  g.setSymbol({
    
    
                      // 线色
                      lineColor: '#34495e',
                      // 线宽
                      lineWidth: 1,
                      // 填充色
                      polygonFill: 'rgb(135,196,240)',
                      // 不透明度
                      polygonOpacity: 0.2
                  })
                  // 设置信息框
                  g.setInfoWindow({
    
    
                      title    : g.properties.name,
                      content  : '<br style="color:#f00">中心点:' + g.properties.center + ' </br>行政区划:' + g.properties.adcode + ' </br>父级行政区划:' + g.properties.parent.adcode + '</div>'
                  })
                  // 鼠标交互事件监听
                  g.on('mouseenter', function (e) {
    
    
                      e.target.updateSymbol({
    
    
                          polygonFill: '#f00'
                      });
                  }).on('mouseout', function (e) {
    
    
                      e.target.updateSymbol({
    
    
                          polygonFill: 'rgb(135,196,240)'
                      });
                  }).on('click', function (e) {
    
    
                      e.target.openInfoWindow(e.coordinate)
                  })
              })
          }
          layer.addGeometry(geometry)
      },

效果如下:

它在鼠标点击位置显示了弹框

image-20211023152155901

基础的操作现在有了,也比较常用,可是你觉得你还需要右键菜单,菜单啊,这个,可以,它也提供了这些东西的设置,下面再来一个简单例子:

 drawAreaPolygon(geoJson, layer) {
    
    
            const _t = this
            const geometry = maptalks.GeoJSON.toGeometry(geoJson)
            if (geometry) {
    
    
                geometry.forEach(g => {
    
    
                    g.setSymbol({
    
    
                        // 线色
                        lineColor: '#34495e',
                        // 线宽
                        lineWidth: 1,
                        // 填充色
                        polygonFill: 'rgb(135,196,240)',
                        // 不透明度
                        polygonOpacity: 0.2
                    })
                    // 设置信息框
                    g.setInfoWindow({
    
    
                        title: g.properties.name,
                        content: '<br style="color:#f00">中心点:' + g.properties.center + ' </br>行政区划:' + g.properties.adcode + ' </br>父级行政区划:' + g.properties.parent.adcode + '</div>'
                    })
                    // 设置右键菜单
                    g.setMenu({
    
    
                        width: 160,
                        custom: false,
                        items: [
                            {
    
     item: '菜单一', click: function() {
    
     alert('Query Clicked!'); return false } },
                            '-',
                            {
    
     item: '菜单二', click: function() {
    
     alert('Edit Clicked!') } },
                            {
    
     item: '菜单三', click: function() {
    
     alert('About Clicked!') } }
                        ]
                    })
                    // 鼠标交互事件监听
                    g.on('mouseenter', function(e) {
    
    
                        e.target.updateSymbol({
    
    
                            polygonFill: '#f00'
                        })
                    }).on('mouseout', function(e) {
    
    
                        e.target.updateSymbol({
    
    
                            polygonFill: 'rgb(135,196,240)'
                        })
                    }).on('click', function(e) {
    
    
                        e.target.openInfoWindow(e.coordinate)
                    })
                })
            }
            layer.addGeometry(geometry)
        },

这里的菜单有一个返回值,如果返回false,菜单就不会关闭。

效果如下:

image-20211023152301838

绘制mark

绘制mark没有Polygon 那么复杂,它只要一个坐标点就行,然后在指定坐标出绘制一个图标,

它有一个addTo方法,可以添加到任何一个图层

drawMark(centerPointList, layer) {
    
    
            if (!centerPointList) {
    
    
                console.log('无区域中心点数据')
                return
            }
            const info = {
    
     content: '', width: 150, minHeight: 100 }
            const result = []
            // 这里 d 的数据格式是数组,如:[-0.113049, 51.498568]
            centerPointList.forEach(d => {
    
    
                if (!d.info) {
    
    
                    d.info = info
                }
                // 设有高度、高亮的mark
                const mark = new maptalks.Marker(d.center, {
    
    
                    // 设置了这个属性,会替换默认的图标
                    // symbol: {
    
    
                        // markerFile: 'foo.png',
                        // textName: d.name
                    // },
                    properties: {
    
    
                        // 高度设置
                        altitude: 50
                    }
                }).addTo(layer)
                mark.setInfoWindow({
    
    
                    title: d.name,
                    content: '<div>' + d.adcode + '</div>',
                    // autoPan: true,
                    width: d.info.width,
                    minHeight: d.info.minHeight,
                    // 'custom': false,
                    // 点击打开和关闭
                    // autoOpenOn: 'click',
                    // autoCloseOn: 'click'
                })

                // 没有高度的mark
                // new maptalks.Marker(d).updateSymbol({
    
    
                //   markerOpacity: 0.5,
                //   markerFill: '#bbb'
                // }).addTo(layer)

                mark.setZIndex(1000)
                result.push(mark)
            })
            return result
        },

这里的centerPointList是geoJson里的properties属性;

绘制三维图形注意点

这里有一个关键点是,要绘制三维的mark,需要设置图层layer启用高度绘制如下:

layer.setOptions({
    
    
        // 启用高度绘制
        enableAltitude: true,
        altitudeProperty: 'altitude',
        // 绘制高度线
        drawAltitude: {
    
    
         // 这里是绘制高度线的宽度,可以理解为Z,那么要透明,这里设置为0
          lineWidth: 1,
          lineColor: '#000'
        }
      })

锁定视角

当启用锁定后,我们所观看到的视图,只会是我们设定好的区域,这块区域默认是地图初始化时设定的center

 lockView() {
    
    
     const extent = this.map.getExtent()
     this.map.setMaxExtent(extent)
 },

猜你喜欢

转载自blog.csdn.net/qq_28911061/article/details/122515814