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>

六、最终效果

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

目录
相关文章
|
算法 JavaScript 数据可视化
基于leaflet-velocity的二维动态风场展示
本文讲解了leaflet-velocity插件,并利用插件进行了模拟的动态风场、洋流等信息的综合展示,让读者掌握集成方式。
1211 0
基于leaflet-velocity的二维动态风场展示
|
API 定位技术 网络架构
leaflet地图介绍
本文将介绍有关于leaflet地图组件在web中的应用 什么是leaflet? leaflet是一个轻量级的开源js地图组件,适用于移动设备,用法简单性能优越,如果你曾经使用过高德或者百度的地图api的话,相信你可以很轻易的上手更加简单的leaflet leaflet是怎么运作的? leaflet的工作方法和高德百度之类的并不一样,由于leaflet是个开源项目,所以它本身只有地图组件并不提供地图内容,也就是说,我们不需要为了使用leaflet而去注册key。
2411 0
|
JavaScript
LeafLet实战-扩展工具栏指南
熟悉LeafLet的都知道,LeafLet自带的工具条只有两个按钮,一个放大和缩小。日常业务中,会用到许多的实用工具,比如测距,量测,如何扩展默认的工具条呢?解决方案如下两种:第一、自己基于dom创建页面元素,并挂载在其默认的工具栏中。第二、基于Leaflet.EasyButton进行扩展。
507 0
LeafLet实战-扩展工具栏指南
干货!layerGroup在LeafLet中的实战
需求场景:boss想针对分子公司进行统一展示,有可能在地图上统一添加、移除、统一调整图标等操作。常规做法可以采用遍历法,去循环所有的marker,批量操作。此时,可以采用layerGroup的方式,将所有分子公司存放在一个layer中,通过分组,可以批量操作存放在layerGroup中
745 0
干货!layerGroup在LeafLet中的实战
|
JavaScript 定位技术 API
vue加载地图,在tab切换到其他页面再切换回来的时候,地图不显示了
vue加载地图,在tab切换到其他页面再切换回来的时候,地图不显示了
1300 0
|
定位技术 API
基于Leaflet.draw的自定义绘制实战
本文介绍了如何基于leaflet.draw进行自定义绘制,同时获取对象的bbox和geojson信息。
860 0
基于Leaflet.draw的自定义绘制实战
|
9月前
|
前端开发 JavaScript
使用 JavaScript 获取 URL 参数的详细指南
【2月更文挑战第26天】
10544 2
使用 JavaScript 获取 URL 参数的详细指南
|
前端开发 JavaScript API
开箱即用的axios封装:Vue3+TS(建议收藏)
Axios多用于处理前端项目的Ajax请求,这里要注意区分Axios和Ajax:Ajax是一种技术统称,Axios是第三方库。在使用的时候,我们可以直接使用Axios来发起请求,也可以封装后采用统一的接口发送请求。在前端项目中,应该大多数人都会选择封装一下Axios,不仅可以节省代码,看起来更简洁;而且可以统一管理请求和响应。本文就以Vue3+Typescript,封装一个”开箱即用“的Axios。
9911 4
开箱即用的axios封装:Vue3+TS(建议收藏)
|
应用服务中间件 Shell Docker
Docker Hub 公有镜像在国内拉取加速配置
通过加速,国内用户能够快速访问最流行的 Docker 镜像。 仓库 registry.docker-cn.com 包含流行的公有镜像。私有镜像仍需要从 Docker Hub 镜像库中拉取。 以下命令直接从镜像加速地址进行拉取: $ docker pull registry.
34939 0
|
6月前
|
Ubuntu NoSQL Linux
一文讲明Docker的基本使用,常见Docker命令使用 、Docker的安装使用等【详细说明+图解+概念+实践】
这篇文章详细介绍了Docker的基本使用,包括Docker的安装、常用命令、架构概念等,并通过图解和实践帮助读者快速掌握Docker的使用方法。
一文讲明Docker的基本使用,常见Docker命令使用 、Docker的安装使用等【详细说明+图解+概念+实践】

热门文章

最新文章