1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > leaflet地图实现滑块放大缩小以及拉框放大缩小

leaflet地图实现滑块放大缩小以及拉框放大缩小

时间:2021-01-12 11:53:06

相关推荐

leaflet地图实现滑块放大缩小以及拉框放大缩小

前言:

最近公司在做一个有关地图的项目,说到地图,就我个人而言,还没接触过,所以拿到项目的时候是一愣一愣的,心想这都是些啥玩意?没办法,既然项目需要,那就得硬着头皮去干,除非你想卷覆盖走人。

需求:

拉动滑块实现地图放大缩小拉框实现地图放大缩小

过程:

拿到需求的时候第一件事当然是找相关的API啦、找文档啦,公司这边要求使用的地图是leaflets地图,所以就得花时间看看leaflet的相关文档。虽然项目已经做的差不多,当由于产品这边提的两个需求刚好在文档里面找不到,也就是leaflet地图没有提供相关的属性(其实不是没有,只是本人对于这个地图了解得不够深入)。所以只能翻墙找相关案例。

一、leaflet 拉动滑块实现地图放大缩小

这个滑块功能我在leaflet地图上没有找到相关的属性,所以自己琢磨了很久也琢磨不出来。当时有想过自己写一下这个功能的,思路如下:

1. 使用 element ui 里面的滑块并且获取到滑块滚动的事件

2. 把滑块等级设置为32级(因为公司项目的地图的放大缩小支持到32级)

3. 滑块每滑动一次就调用一次对应的放大缩小方法(this.map.zoomin 或 this.map.zoomout )

后来发现自己能力有限,虽然思路正确了,但只能实现滑块一级一级的滑动,无法实现越级滑动,所以这个思路无法实现(起码本人无法实现)。

后来靠翻墙才找到相关案例(因为leaflet地图是国外开发的,所以案例在外网会比较多)。leaflet滑块,有需要的可以进去看看,不过需要翻墙,不然进不去。

一、详细写法

如果你使用下面的代码还是无法实现,可以尝试安装一下这个插件npm i leaflet.zoomslider

js代码区域

L.Control.Zoomslider = (function() {var Knob = L.Draggable.extend({initialize: function(element, stepHeight, knobHeight) {L.Draggable.prototype.initialize.call(this, element, element)this._element = elementthis._stepHeight = stepHeightthis._knobHeight = knobHeightthis.on('predrag', function() {this._newPos.x = 0this._newPos.y = this._adjust(this._newPos.y)}, this)},_adjust: function(y) {var value = Math.round(this._toValue(y))value = Math.max(0, Math.min(this._maxValue, value))return this._toY(value)},// y = k*v + m_toY: function(value) {return this._k * value + this._m},// v = (y - m) / k_toValue: function(y) {return (y - this._m) / this._k},setSteps: function(steps) {var sliderHeight = steps * this._stepHeightthis._maxValue = steps - 1// conversion parameters// the conversion is just a common linear function.this._k = -this._stepHeightthis._m = sliderHeight - (this._stepHeight + this._knobHeight) / 2},setPosition: function(y) {L.DomUtil.setPosition(this._element,L.point(0, this._adjust(y)))},setValue: function(v) {this.setPosition(this._toY(v))},getValue: function() {return this._toValue(L.DomUtil.getPosition(this._element).y)}})var Zoomslider = L.Control.extend({options: {position: 'topleft',// Height of zoom-slider.png in pxstepHeight: 6,// Height of the knob div in px (including border)knobHeight: 4,styleNS: 'leaflet-control-zoomslider'},onAdd: function(map) {this._map = mapthis._ui = this._createUI()this._knob = new Knob(this._ui.knob, this.options.stepHeight, this.options.knobHeight)map.whenReady(this._initKnob, this).whenReady(this._initEvents, this).whenReady(this._updateSize, this).whenReady(this._updateKnobValue, this).whenReady(this._updateDisabled, this)return this._ui.bar},onRemove: function(map) {map.off('zoomlevelschange', this._updateSize, this).off('zoomend zoomlevelschange', this._updateKnobValue, this).off('zoomend zoomlevelschange', this._updateDisabled, this)},_createUI: function() {var ui = {}var ns = this.options.styleNSui.bar = L.DomUtil.create('div', ns + ' leaflet-bar'),ui.zoomIn = this._createZoomBtn('in', 'top', ui.bar),ui.wrap = L.DomUtil.create('div', ns + '-wrap leaflet-bar-part', ui.bar),ui.zoomOut = this._createZoomBtn('out', 'bottom', ui.bar),ui.body = L.DomUtil.create('div', ns + '-body', ui.wrap),ui.knob = L.DomUtil.create('div', ns + '-knob')L.DomEvent.disableClickPropagation(ui.bar)L.DomEvent.disableClickPropagation(ui.knob)return ui},_createZoomBtn: function(zoomDir, end, container) {var classDef = this.options.styleNS + '-' + zoomDir +' leaflet-bar-part' +' leaflet-bar-part-' + endvar link = L.DomUtil.create('a', classDef, container)link.href = '#'link.title = 'Zoom ' + zoomDirL.DomEvent.on(link, 'click', L.DomEvent.preventDefault)return link},_initKnob: function() {this._knob.enable()this._ui.body.appendChild(this._ui.knob)},_initEvents: function(map) {this._map.on('zoomlevelschange', this._updateSize, this).on('zoomend zoomlevelschange', this._updateKnobValue, this).on('zoomend zoomlevelschange', this._updateDisabled, this)L.DomEvent.on(this._ui.body, 'click', this._onSliderClick, this)L.DomEvent.on(this._ui.zoomIn, 'click', this._zoomIn, this)L.DomEvent.on(this._ui.zoomOut, 'click', this._zoomOut, this)this._knob.on('dragend', this._updateMapZoom, this)},_onSliderClick: function(e) {var first = (e.touches && e.touches.length === 1 ? e.touches[0] : e)var y = L.DomEvent.getMousePosition(first, this._ui.body).ythis._knob.setPosition(y)this._updateMapZoom()},_zoomIn: function(e) {this._map.zoomIn(e.shiftKey ? 3 : 1)},_zoomOut: function(e) {this._map.zoomOut(e.shiftKey ? 3 : 1)},_zoomLevels: function() {var zoomLevels = this._map.getMaxZoom() - this._map.getMinZoom() + 1return zoomLevels < Infinity ? zoomLevels : 0},_toZoomLevel: function(value) {return value + this._map.getMinZoom()},_toValue: function(zoomLevel) {return zoomLevel - this._map.getMinZoom()},_updateSize: function() {var steps = this._zoomLevels()this._ui.body.style.height = this.options.stepHeight * steps + 'px'this._knob.setSteps(steps)},_updateMapZoom: function() {this._map.setZoom(this._toZoomLevel(this._knob.getValue()))},_updateKnobValue: function() {this._knob.setValue(this._toValue(this._map.getZoom()))},_updateDisabled: function() {var zoomLevel = this._map.getZoom()var className = this.options.styleNS + '-disabled'L.DomUtil.removeClass(this._ui.zoomIn, className)L.DomUtil.removeClass(this._ui.zoomOut, className)if (zoomLevel === this._map.getMinZoom()) {L.DomUtil.addClass(this._ui.zoomOut, className)}if (zoomLevel === this._map.getMaxZoom()) {L.DomUtil.addClass(this._ui.zoomIn, className)}}})return Zoomslider})()L.Map.mergeOptions({zoomControl: false,zoomsliderControl: true})L.Map.addInitHook(function() {if (this.options.zoomsliderControl) {this.zoomsliderControl = new L.Control.Zoomslider()this.addControl(this.zoomsliderControl)}})L.control.zoomslider = function(options) {return new L.Control.Zoomslider(options)}

css代码区域

/** Slider **/.leaflet-control-zoomslider-wrap {padding-top: 5px;padding-bottom: 5px;background-color: #fff;border-bottom: 1px solid #ccc;}.leaflet-control-zoomslider-body {width: 22px;border: solid #fff;border-width: 0px 9px 0px 9px;background-color: rgb(179, 178, 178);margin: 0 auto;}.leaflet-control-zoomslider-knob {position: relative;width: 12px;height: 4px;background-color: #efefef;-webkit-border-radius: 2px;border-radius: 2px;border: 1px solid rgb(179, 178, 178);margin-left: -4px;}.leaflet-control-zoomslider-body:hover {cursor: pointer;}.leaflet-control-zoomslider-knob:hover {cursor: default;cursor: -webkit-grab;cursor: -moz-grab;}.leaflet-dragging .leaflet-control-zoomslider,.leaflet-dragging .leaflet-control-zoomslider-wrap,.leaflet-dragging .leaflet-control-zoomslider-body,.leaflet-dragging .leaflet-control-zoomslider a,.leaflet-dragging .leaflet-control-zoomslider a.leaflet-control-zoomslider-disabled,.leaflet-dragging .leaflet-control-zoomslider-knob:hover {cursor: move;cursor: -webkit-grabbing;cursor: -moz-grabbing;}/** Leaflet Zoom Styles **/.leaflet-container .leaflet-control-zoomslider {margin-left: 10px;margin-top: 50px;}.leaflet-control-zoomslider a {width: 24px;height: 26px;text-align: center;text-decoration: none;color: black; display: block;}.leaflet-control-zoomslider a:hover {width: 24px;background-color: #f4f4f4;}.leaflet-control-zoomslider-in {font: bold 18px 'Lucida Console', Monaco, monospace;}.leaflet-control-zoomslider-in:after{content:"+"}.leaflet-control-zoomslider-out {font: bold 22px 'Lucida Console', Monaco, monospace;}.leaflet-control-zoomslider-out:after{content:"-"}.leaflet-control-zoomslider a.leaflet-control-zoomslider-disabled {cursor: default;color: #bbb;}/* Touch */.leaflet-touch .leaflet-control-zoomslider-body {background-position: 10px 0px;}.leaflet-touch .leaflet-control-zoomslider-knob {width: 16px;margin-left: -7px;}.leaflet-touch .leaflet-control-zoomslider a {width: 30px;line-height: 30px;}.leaflet-touch .leaflet-control-zoomslider a:hover {width: 30px;line-height: 30px;}.leaflet-touch .leaflet-control-zoomslider-in {font-size: 24px;line-height: 29px;}.leaflet-touch .leaflet-control-zoomslider-out {font-size: 28px;line-height: 30px;}.leaflet-touch .leaflet-control-zoomslider {box-shadow: none;border: 4px solid rgba(0,0,0,0.3);}

二、简单粗暴法

对于看不懂的或者想偷懒的程序猿来说,复制粘贴是最快的方法,如果你不想动脑筋,可以把下面的两个文件直接复制粘贴到你的项目里面去,然后直接引用就可以了

滑块放大缩小的css

滑块放大缩小的js

引用:

在你的vue文件里把对应的js文件与css文件引入即可

效果:

二、leaflet 拉框放大

对于拉框放大,相信很多人都能从leaflet的相关文档里面找到它的相关属性,都知道按着Shift键加鼠标就可以实现拉框放大,但用户不知道啊,所以我们得把它显示到界面上。但leaflet只提供了相关的属性,并没有提供相关的用法,这就让人很苦恼。你不可能把Shift键当成一个按钮显示到页面上,当用户点击时按钮状态一直为true,这样的话如果Shift键在这时有什么用处,那这就会产生冲突,这明显不是最佳的解决方法。下面,我就给大家呈上正确的方法。

案例

leaflet拉框缩小

一、详细解决方法

js代码区域

/** L.Control.BoxZoom* A visible, clickable control for doing a box zoom.* /gregallensworth/L.Control.BoxZoom*/L.Control.BoxZoom = L.Control.extend({options: {position: 'topright',title: 'Click here then draw a square on the map, to zoom in to an area',aspectRatio: null,divClasses: '',enableShiftDrag: false,iconClasses: '',keepOn: true,},initialize: function(options) {L.setOptions(this, options);this.map = null;this.active = false;},onAdd: function (map) {// add a linkage to the map, since we'll be managing map layersthis.map = map;this.active = false;// create our button: uses FontAwesome cuz that font is... awesome// assign this here control as a property of the visible DIV, so we can be more terse when writing click-handlers on that visible DIVthis.controlDiv = L.DomUtil.create('div', 'leaflet-control-boxzoom');// if we're not using an icon, add the background image classif (!this.options.iconClasses) {L.DomUtil.addClass(this.controlDiv, 'with-background-image');}if (this.options.divClasses) {L.DomUtil.addClass(this.controlDiv, this.options.divClasses);}this.controlDiv.control = this;this.controlDiv.title= this.options.title;this.controlDiv.innerHTML = ' ';L.DomEvent.addListener(this.controlDiv, 'mousedown', L.DomEvent.stopPropagation).addListener(this.controlDiv, 'click', L.DomEvent.stopPropagation).addListener(this.controlDiv, 'click', L.DomEvent.preventDefault).addListener(this.controlDiv, 'click', function () {this.control.toggleState();});// start by toggling our state to off; this disables the boxZoom hooks on the map, in favor of this onethis.setStateOff();if (this.options.iconClasses) {var iconElement = L.DomUtil.create('i', this.options.iconClasses, this.controlDiv);if (iconElement) {iconElement.style.color = this.options.iconColor || 'black';iconElement.style.textAlign = 'center';iconElement.style.verticalAlign = 'middle';} else {console.log('Unable to create element for icon');}}// if we're enforcing an aspect ratio, then monkey-patch the map's real BoxZoom control to support that// after all, this control is just a wrapper over the map's own BoxZoom behaviorif (this.options.aspectRatio) {this.map.boxZoom.aspectRatio = this.options.aspectRatio;this.map.boxZoom._onMouseMove = this._boxZoomControlOverride_onMouseMove;this.map.boxZoom._onMouseUp = this._boxZoomControlOverride_onMouseUp;}// done!return this.controlDiv;},onRemove: function (map) {// on remove: if we had to monkey-patch the aspect-ratio stuff, undo that nowif (this.options.aspectRatio) {delete this.map.boxZoom.aspectRatio;this.map.boxZoom._onMouseMove = L.Map.BoxZoom.prototype._onMouseMove;this.map.boxZoom._onMouseUp = L.Map.BoxZoom.prototype._onMouseUp;}},toggleState: function () {this.active ? this.setStateOff() : this.setStateOn();},setStateOn: function () {L.DomUtil.addClass(this.controlDiv,'leaflet-control-boxzoom-active');this.active = true;this.map.dragging.disable();if (!this.options.enableShiftDrag) {this.map.boxZoom.addHooks();}this.map.on('mousedown', this.handleMouseDown, this);if (!this.options.keepOn) {this.map.on('boxzoomend', this.setStateOff, this);}L.DomUtil.addClass(this.map._container,'leaflet-control-boxzoom-active');},setStateOff: function () {L.DomUtil.removeClass(this.controlDiv,'leaflet-control-boxzoom-active');this.active = false;this.map.off('mousedown', this.handleMouseDown, this);this.map.dragging.enable();if (!this.options.enableShiftDrag) {this.map.boxZoom.removeHooks();}L.DomUtil.removeClass(this.map._container,'leaflet-control-boxzoom-active');},handleMouseDown: function (event) {this.map.boxZoom._onMouseDown.call(this.map.boxZoom, {clientX:event.originalEvent.clientX, clientY:event.originalEvent.clientY, which:1, shiftKey:true });},// monkey-patched applied to L.Map.BoxZoom to handle aspectRatio and to zoom to the drawn box instead of the mouseEvent point// in these methods, "this" is not the control, but the map's boxZoom instance_boxZoomControlOverride_onMouseMove: function (e) {if (!this._moved) {this._box = L.DomUtil.create('div', 'leaflet-zoom-box', this._pane);L.DomUtil.setPosition(this._box, this._startLayerPoint);//TODO refactor: move cursor to stylesthis._container.style.cursor = 'crosshair';this._map.fire('boxzoomstart');}var startPoint = this._startLayerPoint,box = this._box,layerPoint = this._map.mouseEventToLayerPoint(e),offset = layerPoint.subtract(startPoint),newPos = new L.Point(Math.min(layerPoint.x, startPoint.x),Math.min(layerPoint.y, startPoint.y));L.DomUtil.setPosition(box, newPos);this._moved = true;var width = (Math.max(0, Math.abs(offset.x) - 4)); // from L.Map.BoxZoom, TODO refactor: remove hardcoded 4 pixelsvar height = (Math.max(0, Math.abs(offset.y) - 4)); // from L.Map.BoxZoom, TODO refactor: remove hardcoded 4 pixelsif (this.aspectRatio) {height = width / this.aspectRatio;}box.style.width = width + 'px';box.style.height = height + 'px';},_boxZoomControlOverride_onMouseUp: function (e) {// the stock behavior is to generate a bbox based on the _startLayerPoint and the mouseUp event point// we don't want that; we specifically want to use the drawn box with the fixed aspect ratio// fetch the box and convert to a map bbox, before we clear itvar ul = this._box._leaflet_pos;var lr = new L.Point(this._box._leaflet_pos.x + this._box.offsetWidth, this._box._leaflet_pos.y + this._box.offsetHeight);var nw = this._map.layerPointToLatLng(ul);var se = this._map.layerPointToLatLng(lr);if (nw.equals(se)) {return; }this._finish();var bounds = new L.LatLngBounds(nw, se);this._map.fitBounds(bounds);this._map.fire('boxzoomend', {boxZoomBounds: bounds});},});L.Control.boxzoom = function(options) {return new L.Control.BoxZoom(options);}

css代码区域

/** BOXZOOM*/.leaflet-control-boxzoom {background-color:white;border-radius:4px;border:1px solid #cccccc;width:25px;height:25px;line-height:25px;box-shadow:0 1px 2px rgba(0,0,0,0.65);cursor:pointer !important;}.with-background-image {background-image:url(leaflet-control-boxzoom.svg);background-repeat:no-repeat;background-size:21px 21px; /* 25px image, 25px box; subtract 2px for padding on every side = 21px rendering height */background-position:2px 2px;}.leaflet-control-boxzoom.leaflet-control-boxzoom-active {background-color:#aaaaaa;}.leaflet-container.leaflet-control-boxzoom-active, .leaflet-container.leaflet-control-boxzoom-active path.leaflet-interactive {cursor:crosshair !important;}.leaflet-control-boxzoom i {display:block;}.leaflet-control-boxzoom i.icon {font-size:17px;margin-left:1px;margin-top:3px;}.leaflet-control-boxzoom i.fa {margin-top:6px;}.leaflet-control-boxzoom i.glyphicon {margin-top:5px;}

二,快速解决法

对于懒惰的人来说,我还给他准备了快速的解决方法,直接复制粘贴(注意:文件都是配套的,不可复制少文件)

拉框放大的js文件

拉框放大的css文件

拉框放大的svg文件

引用方法

与滑块引用方法一样,把代码路径引进来

再到相关配置文件里面把它 addTo 到地图上面去,就可以正常使用啦。

L.Control.boxzoom({ position: ‘topleft’ }).addTo(map)

效果:

对于拉框缩小来说,鄙人还没有找到相关的属于以及解决方法,等后续找到相关方法,再给大家接上。或者你已经有解决方法,也麻烦教一下,毕竟甲方需求必须完成,谢谢。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。