5分钟学会Leaflet加载天地图和arcgis服务

Leaflet是一个适用于移动端交互地图的开源JavaScript库。

对移动设备很友好,gzip压缩JS代码大约38 KB,它提供了大多数开发人员所需要的所有地图功能。

扩展性强、插件资源丰富,文档清晰的API,源代码简单、易读。

本文用简单的示例,引导新手快速使用leaflet快速开始、加载天地图、加载arcgis服务、自定义4490坐标系,将天地图扩展到19级。

一、快速开始

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Quick Start - Leaflet</title>
  <link rel="stylesheet" href="./css/leaflet.css">
  <style>
    *{
      margin: 0;
      padding: 0;
    }
    #map {
      height: 100vh;
      width: 100vw;
    }
  </style>
</head>
<body>
  <div id="map"></div>
  <script src="./js/leaflet-src.js"></script>
  <script>
    var map = L.map('map').setView([39.736861245030326, 116.13991336098002], 13);
    L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png').addTo(map);
    L.marker([39.736861245030326, 116.13991336098002]).addTo(map)
      .bindPopup('marker')
      .openPopup();
  </script>
</body>
</html>

 示例效果

 以上代码实现了Leaflet的引入,地图的加载及marker的简单用法,接下来开始加载天地图。

二、加载天地图

1.去天地图官网获取天地图服务许可(Key

2.引入leaflet.ChineseTmsProviders

3.将leaflet.ChineseTmsProviders中的key换成自己申请的key

4.初始化地图实例并加载天地图

<script>
    const tileOptions = {
      minZoom: 1,
      maxZoom: 19
    }
    // 定义矢量地图
    var normalm = L.tileLayer.chinaProvider('TianDiTu.Normal.Map', tileOptions)
    // 定义矢量注记
    var normala = L.tileLayer.chinaProvider('TianDiTu.Normal.Annotion', tileOptions)
    // 组合地图和注记
    var normal = L.layerGroup([normalm, normala])
    var map = L.map('map', {
      center: [39.736861245030326, 116.13991336098002],
      zoom: 16,
      layers: [normal]
    })
    let marker = L.marker([39.736861245030326, 116.13991336098002]).addTo(map)
</script>

  示例效果

三、加载Arcgis服务

1.引入esri-leaflet.jsesri-leaflet-renderers.js

<script src="./js/esri-leaflet.js"></script>
<script src="./js/esri-leaflet-renderers.js"></script>

2.加载arcgis服务

<script>
    const tileOptions = {
      minZoom: 1,
      maxZoom: 19
    }
    // 定义矢量地图
    var normalm = L.tileLayer.chinaProvider('TianDiTu.Normal.Map', tileOptions)
    // 定义矢量注记
    var normala = L.tileLayer.chinaProvider('TianDiTu.Normal.Annotion', tileOptions)
    // 组合地图和注记
    var normal = L.layerGroup([normalm, normala])
    var map = L.map('map', {
      center: [39.736861245030326, 116.13991336098002],
      zoom: 16,
      layers: [normal]
    })
    let marker = L.marker([39.736861245030326, 116.13991336098002]).addTo(map)

    const mapServerUrl = 'http://你项目的arcgis服务地址/MapServer/0'
    let mapLayer = L.esri.featureLayer({
      url: mapServerUrl
    }).addTo(map)
</script>

  示例效果

四、自定义4490坐标(Leaflet默认为EPSG3857)

1.引入proj4-src.jsproj4leaflet.js

<script src="./js/proj4-src.js"></script>
<script src="./js/proj4leaflet.js"></script>

2.定义缩放比例和原点(参数可以在https://epsg.io/4490参看,定义其他坐标系同理)

const CRS_4490 = new L.Proj.CRS(
      'EPSG:4490',
      '+proj=longlat +ellps=GRS80 +no_defs', {
        resolutions: [
          1.40625,
          0.703125,
          0.3515625,
          0.17578125,
          0.087890625,
          0.0439453125,
          0.02197265625,
          0.010986328125,
          0.0054931640625,
          0.00274658203125,
          0.001373291015625,
          6.866455078125e-4,
          3.4332275390625e-4,
          1.71661376953125e-4,
          8.58306884765625e-5,
          4.291534423828125e-5,
          2.1457672119140625e-5,
          1.0728836059570312e-5,
          5.364418029785156e-6,
          2.682209064925356e-6,
          1.3411045324626732e-6,
          6.705522662313365e-7,
        ],
        origin: [-180, 90],
      }
    )

3.在地图实例中赋值自定义的坐标系

var map = L.map('map', {
    center: [39.736861245030326, 116.13991336098002],
    zoom: 16,
    layers: [normal],
    crs: CRS_4490
})

4.修改leaflet.ChineseTmsProviderst.js文件,将天地图墨卡托投影改成经纬度(因为4490是地理坐标系),也就是将上文加载天地图模块的第三点,改成下面这段代码,w代表墨卡托,c代表经纬度

TianDiTu: {
		Normal: {
			Map:
				'https://t{s}.tianditu.gov.cn/vec_c/wmts?layer=vec&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&tileMatrix={z}&TileCol={x}&TileRow={y}&tk={key}',
			Annotion:
				'https://t{s}.tianditu.gov.cn/cva_c/wmts?layer=cva&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&tileMatrix={z}&TileCol={x}&TileRow={y}&tk={key}',
		},
		Satellite: {
			Map:
				'https://t{s}.tianditu.gov.cn/img_c/wmts?layer=img&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&tileMatrix={z}&TileCol={x}&TileRow={y}&tk={key}',
			Annotion:
				'https://t{s}.tianditu.gov.cn/cia_c/wmts?layer=cia&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&tileMatrix={z}&TileCol={x}&TileRow={y}&tk={key}',
		},
		Terrain: {
			Map:
				'https://t{s}.tianditu.gov.cn/ter_c/wmts?layer=ter&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&tileMatrix={z}&TileCol={x}&TileRow={y}&tk={key}',
			Annotion:
				'https://t{s}.tianditu.gov.cn/cta_c/wmts?layer=cta&style=default&tilematrixset=c&Service=WMTS&Request=GetTile&Version=1.0.0&Format=tiles&tileMatrix={z}&TileCol={x}&TileRow={y}&tk={key}',
		},
  	Subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
    key: "自己在天地图官网申请的key"
  },

五、拓展天地图到19级

1.修改leaflet-src.js源码

createTile方法中的tile.src = this.getTileUrl(coords)修改如下:

if(coords.z == 19) {
	let coords_18 = new Point(Math.floor(coords.x / 2), Math.floor(coords.y / 2), 19)
	let tileUrl = this.getTileUrl(coords_18)
	tileUrl = tileUrl.replace('tileMatrix=19', 'tileMatrix=18')
	// 加载18级图片回来,进行切割,四等份
	let img = new Image()
	img.src = tileUrl +'&v='+ Math.random()
	img.crossOrigin = 'anonymous'
	img.onload = function() {
	let c = document.createElement('canvas');
    let ctx = c.getContext('2d');
    c.width = 256;
    c.height = 256;
	ctx.drawImage(img, coords.x % 2 *128, coords.y % 2 * 128, 128, 128, 0, 0, 256, 256);
		tile.src = c.toDataURL() // 默认为 PNG 格式。图片的分辨率为96dpi。
	}
} else {
	tile.src = this.getTileUrl(coords);
}

原理:将18级瓦片进行2次方切割,用canvas重画,同理拓展到20级的时候进行2的2次方切割,21级时进行2的3次方切割,以此类推,这样处理可以打破天地图18级的限制,但由于是将18级的瓦片切割放大的,带来的弊端是级别越大,地图越模糊。

2.修改maxZoom,本文将天地图拓展到19级,因此设最大缩放级别为19。各位可根据项目需求进行相应修改。

const tileOptions = {
    minZoom: 1,
    maxZoom: 19
}

 


版权声明:本文为yisimo原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。