Leaflet中如何限制地图的拖动范围

简介: 本文讲解了在Leaflet中如何进行地图范围的控制,并通过代码的方式进行示例,并展示了最终效果。

一、背景

      在Leaflet默认的地图载模式中,假如没有对地图的一个范围进行限制,那就会带来一个问题,随着地图可以拖动,当地图往右拖动越多,每跨一屏(这里的一屏指地图投影后在页面上的平铺位置)经度会加360度。同理,如果往左边拖一屏,也是相应的嫌少-360度。这是目标点的一个定位问题。


       第二个问题是,假如我们在,[120.146484,29.649869]这个点标一个marker,你会发现,当拖动一屏后,它并没有在同一个位置也标上这个点。如果把此时的地图给用户看的话,肯定会产生一种错觉。


二、问题展示

     1、经度大于180度的场景

       使用鼠标拖拽地图到右边,使用鼠标选点展示坐标可以看到,此时坐标的经度468.984375,明显超出了正常经度的范围值。  

2、经度小于-180度的场景

       使用鼠标拖拽地图到左边,使用鼠标选点展示坐标可以看到,此时坐标的经度 -241.171875,明显超出了正常经度的范围值。

3、marker标错

       使用如下代码进行一个marker的标定,你会发现,无论将地图往左边拖或者右边拖,地图上始终只有一个点。

L.marker([22.024546, 110.654297]).addTo(mymap)
    .bindPopup("<b>Hello world!</b><br/>我是一个提示框.").openPopup();

三、原因分析

       造成以上问题的原因是什么呢?众所周知,在地理信息系统中,对地理范围是有一个明确的定义的。经度范围是0-180°,纬度范围是0-90°。从0°经线算起,向东、向西各分作180°,以东的180°属于东经,习惯上用“百E”作代号,以西的180°属于西经,习惯上用“W”作代号。我们通常说的纬度度指的是大地纬度。其数值在0至90度之间。位于赤道以北的点的纬度叫北纬,记为N;位于赤道以南的点的纬度称南纬,记为S。为了研究问题方便,人们把纬度分问为低、 中、高纬度。0°~30°为低纬度, 30°~ 60°为中纬度, 60~90°为高纬度。


了解了上述的知识后就知道了解决上述问题的办法,只需要在Leaflet中定义地图时,限制以下地图的经纬度范围。

四、Leaflet API

     通过查找Leaflet的api我们发现了,在地图参数中有以下的定义:

image.png

默认的情况下,maxBounds参数设置为空。设置此选项后,地图会将视图限制在给定的地理范围内,如果用户试图在视图之外平移,则将用户弹回。要动态设置限制,请使用 setMaxBounds方法。通过这种方式就能限制地图的最大范围。

五、代码实现

1、leaflet资源引入

<head><title>经纬度投影-限制地图拖动范围</title><metacharset="utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"><linkrel="shortcut icon"type="image/x-icon"href="docs/images/favicon.ico"/><linkrel="stylesheet"href="/2d/leaflet/leaflet.css"/><scriptsrc="/2d/leaflet/leaflet.js?v=1.0.0"></script></head>

2、地图定义

L.CRS.CustomEPSG4326=L.extend({}, L.CRS.Earth, {
code: 'EPSG:4326',
projection: L.Projection.LonLat,
transformation: newL.Transformation(1/180, 1, -1/180, 0.5),
scale: function (zoom) {
return256*Math.pow(2, zoom-1);
    }
  });
// 第一种设置方式,可行//限制地图的拖动范围是正负90到正负180,这样才合理。varcorner1=L.latLng(-90, -180); //设置左上角经纬度varcorner2=L.latLng(90, 180);  //设置右下点经纬度varbounds=L.latLngBounds(corner1, corner2); //构建视图限制范varmymap=L.map('mapid',{crs:L.CRS.CustomEPSG4326,maxBounds:bounds}).setView([29.052934, 104.0625], 5);

这里的关键代码就是如下代码,通过这两个位置来限制拖动情况。地图的定义在crs这里,我使用了一个自己的转换规则,这取决你的瓦片读取方式。如果标准的WGS84投影,可以不需要这么定义,直接使用默认的方式加载即可。

var corner1 =  L.latLng(-90, -180); //设置左上角经纬度
var corner2 = L.latLng(90, 180);  //设置右下点经纬度
var bounds = L.latLngBounds(corner1, corner2); //构建视图限制范围

除了使用这种初始定义的方式,还可以使用setMaxBounds(args)这种函数调用来进行,效果是一样的,调用代码:mymap.setMaxBounds(bounds);这种方式对控制显得更灵活方便。

3、完整代码实例

<!DOCTYPE html><html><head><title>经纬度投影-限制地图拖动范围</title><metacharset="utf-8"/><metaname="viewport"content="width=device-width, initial-scale=1.0"><linkrel="shortcut icon"type="image/x-icon"href="docs/images/favicon.ico"/><linkrel="stylesheet"href="/2d/leaflet/leaflet.css"/><scriptsrc="/2d/leaflet/leaflet.js?v=1.0.0"></script></head><body><divid="mapid"style="width: 100%; height: 600px;"></div><script>L.CRS.CustomEPSG4326=L.extend({}, L.CRS.Earth, {
code: 'EPSG:4326',
projection: L.Projection.LonLat,
transformation: newL.Transformation(1/180, 1, -1/180, 0.5),
scale: function (zoom) {
return256*Math.pow(2, zoom-1);
    }
  });
// 第一种设置方式,可行//限制地图的拖动范围是正负90到正负180,这样才合理。/*var corner1 =  L.latLng(-90, -180); //设置左上角经纬度    var corner2 = L.latLng(90, 180);  //设置右下点经纬度    var bounds = L.latLngBounds(corner1, corner2); //构建视图限制范围  var mymap = L.map('mapid',{crs:L.CRS.CustomEPSG4326,maxBounds:bounds}).setView([29.052934, 104.0625], 5);*/varcorner1=L.latLng(-90, -180); //设置左上角经纬度varcorner2=L.latLng(90, 180);  //设置右下点经纬度varbounds=L.latLngBounds(corner1, corner2); //构建视图限制范围varmymap=L.map('mapid',{crs:L.CRS.CustomEPSG4326}).setView([29.052934, 104.0625], 5);
//第二种设置方式,可行//mymap.setMaxBounds(bounds);L.tileLayer('http://localhost:8086/data/basemap_nowater/1_10_tms/{z}/{x}/{y}.jpg', {
maxZoom: 16,
attribution: 'yelangkingMap data &copy; <a href="https://www.openstreetmap.org/">本地瓦片加载</a> contributors, '+'<a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, '+'Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
id: 'mapbox/streets-v11',
tileSize: 256,
zoomOffset: -1  }).addTo(mymap);
//标签L.tileLayer('http://localhost:8086/data/basemap_nowater/1-10label/{z}/{x}/{y}.png', {maxZoom: 10,minZoom:3,
id: 'mapbox/label',tileSize: 256,zoomOffset: -1  }).addTo(mymap);
L.marker([22.024546, 110.654297]).addTo(mymap)
    .bindPopup("<b>Hello world!</b><br />我是一个提示框.").openPopup();
L.circle([29.649869, 120.146484], 99000, {
color: 'red',
fillColor: '#f03',
fillOpacity: 0.5  }).addTo(mymap).bindPopup("我是一个圆.");
L.polygon([
    [32.916485, 101.601563],
    [30.562261, 105.556641],
    [34.524661, 108.149414]
  ]).addTo(mymap).bindPopup("我是一个多边形.");
varpopup=L.popup();
functiononMapClick(e) {
popup.setLatLng(e.latlng)
      .setContent("当前坐标为:"+e.latlng.toString())
      .openOn(mymap);
  }
mymap.on('click', onMapClick);
</script></body></html>

六、最终效果

      最终我们可以在界面上看到,当你想拖动地图到左边或者右边时,地图会默认弹回。这样就合理的避免了坐标太大超出范围的问题,以及点在地图上的标定问题。

目录
相关文章
|
定位技术 API 网络架构
地图图层接入:从mapbox转向cesium
由于地图坐标系的不统一,地图图商提供的图层服务也各有特色,在图层对接的开发过程中常会遇到许多坑,从二维图层到三维图层,地图引擎mapbox再到cesium,本文将分享笔者在近期地图图层接入过程中总结的一些经验。
3329 10
|
2月前
|
JavaScript 搜索推荐 定位技术
【百度地图2.5D、3D在Vue项目中的使用】嵌入二维百度地图、三维百度地图、多种显示模式风格样式颜色的百度地图
【百度地图2.5D、3D在Vue项目中的使用】嵌入二维百度地图、三维百度地图、多种显示模式风格样式颜色的百度地图
|
2月前
|
测试技术 定位技术
【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动
【sgDragMoveTile】自定义组件:拖拽瓦片图、地图、大图,滚动条对应同步滚动
|
12月前
|
定位技术
百度地图开发(8):地图覆盖物实现纵横交错的交通网络
百度地图开发(8):地图覆盖物实现纵横交错的交通网络
33 0
百度地图开发(8):地图覆盖物实现纵横交错的交通网络
|
12月前
|
定位技术 API
Cesium开发:限制地图浏览范围
Cesium开发:限制地图浏览范围
490 1
|
12月前
|
定位技术 API
Cesium开发:常用地图事件
Cesium开发:常用地图事件
247 0
|
定位技术 数据库
利用 QGIS 绘制洞穴地图
利用 QGIS 绘制洞穴地图
151 0
利用 QGIS 绘制洞穴地图
|
前端开发 JavaScript 定位技术
基于OpenLayers实现导航地图上(起/终)点的交互式图标显示
基于OpenLayers实现导航地图上(起/终)点的交互式图标显示
267 0
基于OpenLayers实现导航地图上(起/终)点的交互式图标显示
|
定位技术 开发者
地图控件|学习笔记
快速学习地图控件
83 0
地图控件|学习笔记
|
JavaScript
Vue环境下用ECharts绘制中国地图,并实现拖动、缩放与各省份自动轮播高亮显示
Vue环境下用ECharts绘制中国地图,并实现拖动、缩放与各省份自动轮播高亮显示
1090 0
Vue环境下用ECharts绘制中国地图,并实现拖动、缩放与各省份自动轮播高亮显示