UNPKG

openlayermap

Version:

openlayer Map Component for Vue 2.0

450 lines (416 loc) 12 kB
/** * Created by FDD on 2017/10/12. * @desc 自定义鹰眼控件 */ import '../asset/scss/overviewMap.css' import ol from 'openlayers' import {BASE_CLASS_NAME, OVERVIEWMAP} from '../constants' import DomUtils from 'nature-dom-util' const htmlUtils = DomUtils.htmlUtils const Events = DomUtils.Events ol.control.OverviewMapH = function (options = {}) { /** * @type {boolean} * @private */ this.collapsed_ = options.collapsed !== undefined ? options.collapsed : false /** * @private * @type {boolean} */ this.collapsible_ = options.collapsible !== undefined ? options.collapsible : false if (!this.collapsible_) { this.collapsed_ = false } // 设置 let className = options.className !== undefined ? options.className : 'hmap-overview-map' let element = htmlUtils.create('div', className + ' ' + BASE_CLASS_NAME.CLASS_UNSELECTABLE) /** * @type {Element} * @private */ this.ovmapDiv_ = htmlUtils.create('div', 'hmap-overview-map-target', element) /** * 收起按钮 * @type {Element} * @private */ if (this.collapsible_) { this.collapsElement_ = htmlUtils.create('div', 'hmap-overview-map-button', element) Events.listen(this.collapsElement_, 'click', this.handleClick_, this) } /** * @type {ol.Map} * @private 鹰眼对应的地图容器--- */ this.ovmap_ = new ol.Map({ controls: new ol.Collection(), interactions: new ol.Collection(), view: options.view }) let render = options.render ? options.render : ol.control.OverviewMapH.render // 以子类实例为上下文调用父类构造---- ol.control.Control.call(this, { element: element, render: render, target: options.target }) this.addBoxControl_() } ol.inherits(ol.control.OverviewMapH, ol.control.Control) // 继承父类构造 /** * 添加图层 * @param options * @private */ ol.control.OverviewMapH.prototype.addOptionLayers_ = function (options) { let ovmap = this.ovmap_ // 获取鹰眼 if (options.layers) { options.layers.forEach(function (layer) { ovmap.addLayer(layer) }, this) } } /** * 计算鼠标位置 * @param mousePosition * @returns {{clientX: number, clientY: *}} */ ol.control.OverviewMapH.computeDesiredMousePosition = function (mousePosition, overlayBox) { return { clientX: mousePosition.clientX - (overlayBox.offsetWidth / 2), clientY: mousePosition.clientY + (overlayBox.offsetHeight / 2) } } /** * 处理移动事件 * @private */ ol.control.OverviewMapH.prototype.move_ = function (event) { const overlayBox = this.boxOverlay_.getElement() let coordinates = this.ovmap_.getEventCoordinate(ol.control.OverviewMapH.computeDesiredMousePosition(event, overlayBox)) this.boxOverlay_.setPosition(coordinates) } /** * 移动结束事件 * @param event * @private */ ol.control.OverviewMapH.prototype.endMoving_ = function (event) { let coordinates = this.ovmap_.getEventCoordinate(event) this.getMap().getView().setCenter(coordinates) Events.unListen(window, 'mousemove', this.move_, this) Events.unListen(window, 'mouseup', this.endMoving_, this) } /** * 添加事件 * @private */ ol.control.OverviewMapH.prototype.addEvent_ = function () { Events.listen(window, 'mousemove', this.move_, this) Events.listen(window, 'mouseup', this.endMoving_, this) } /** * 添加box * @private */ ol.control.OverviewMapH.prototype.addBoxControl_ = function () { let box = htmlUtils.create('div', 'hmap-overview-map-box') Events.listen(box, 'mousedown', this.addEvent_, this) this.boxOverlay_ = new ol.Overlay({ position: [0, 0], positioning: 'bottom-left', element: box }) this.ovmap_.addOverlay(this.boxOverlay_) } /** * setMap * @param map 重新父类此方法---- */ ol.control.OverviewMapH.prototype.setMap = function (map) { let oldMap = this.getMap() if (map === oldMap) { return } if (oldMap) { let oldView = oldMap.getView() if (oldView) { this.unbindView_(oldView) } this.ovmap_.setTarget(null) } ol.control.Control.prototype.setMap.call(this, map) if (map) { this.ovmap_.setTarget(this.ovmapDiv_) // 设置鹰眼地图显示图层的时机,当其添加到地图时显示 Events.listen(map, 'propertychange', this.handleMapPropertyChange_, this) if (this.ovmap_.getLayers().getLength() === 0) { this.ovmap_.setLayerGroup(map.getLayerGroup()) } let view = map.getView() if (view) { this.bindView_(view) if (this.isDef(view)) { this.ovmap_.updateSize() this.resetExtent_() } } } } /** * 判断视图是否定义 * @param view * @returns {boolean} */ ol.control.OverviewMapH.prototype.isDef = function (view) { return !!view.getCenter() && view.getResolution() !== undefined } /** * 处理地图属性变化 * @param event * @private */ ol.control.OverviewMapH.prototype.handleMapPropertyChange_ = function (event) { if (event.key === 'view') { let oldView = (event.oldValue) if (oldView) { this.unbindView_(oldView) } let newView = this.getMap().getView() this.bindView_(newView) } } /** * 注册视图变化事件 * @param view * @private */ ol.control.OverviewMapH.prototype.bindView_ = function (view) { Events.listen(view, 'change:rotation', this.handleRotationChanged_, this) } /** * 取消视图事件绑定 * @param view * @private */ ol.control.OverviewMapH.prototype.unbindView_ = function (view) { Events.unListen(view, 'change:rotation', this.handleRotationChanged_, this) } /** * 处理视图旋转 * @private 保持地图和鹰眼容器地图旋转角度的一致性---- */ ol.control.OverviewMapH.prototype.handleRotationChanged_ = function () { this.ovmap_.getView().setRotation(this.getMap().getView().getRotation()) } /** * 更新控件要素 * @param mapEvent */ ol.control.OverviewMapH.render = function (mapEvent) { this.validateExtent_() this.updateBox_() } /** * 重新调整范围,避免过大或者过小 * @private */ ol.control.OverviewMapH.prototype.validateExtent_ = function () { let map = this.getMap() // 主地图对象--- let ovmap = this.ovmap_ // 鹰眼地图对象---- let mapSize = /** @type {ol.Size} */ (map.getSize()) // 主地图对象大小--- let view = map.getView() // 主地图视图 let extent = view.calculateExtent(mapSize) // 主地图视图范围 let ovmapSize = /** @type {ol.Size} */ (ovmap.getSize()) let ovview = ovmap.getView() let ovextent = ovview.calculateExtent(ovmapSize) let topLeftPixel = ovmap.getPixelFromCoordinate(ol.extent.getTopLeft(extent)) if (!topLeftPixel) { return } let bottomRightPixel = ovmap.getPixelFromCoordinate(ol.extent.getBottomRight(extent)) if (!bottomRightPixel) { return } let boxWidth = Math.abs(topLeftPixel[0] - bottomRightPixel[0]) let boxHeight = Math.abs(topLeftPixel[1] - bottomRightPixel[1]) let ovmapWidth = ovmapSize[0] let ovmapHeight = ovmapSize[1] if (boxWidth < ovmapWidth * OVERVIEWMAP.MIN_RATIO || boxHeight < ovmapHeight * OVERVIEWMAP.MIN_RATIO || boxWidth > ovmapWidth * OVERVIEWMAP.MAX_RATIO || boxHeight > ovmapHeight * OVERVIEWMAP.MAX_RATIO) { this.resetExtent_() } else if (!ol.extent.containsExtent(ovextent, extent)) { this.recenter_() } } /** * 重新设置视图范围 * @private */ ol.control.OverviewMapH.prototype.resetExtent_ = function () { if (OVERVIEWMAP.MAX_RATIO === 0 || OVERVIEWMAP.MIN_RATIO === 0) { return } let map = this.getMap() let ovmap = this.ovmap_ let mapSize = /** @type {ol.Size} */ (map.getSize()) let view = map.getView() let extent = view.calculateExtent(mapSize) let ovview = ovmap.getView() let steps = Math.log( OVERVIEWMAP.MAX_RATIO / OVERVIEWMAP.MIN_RATIO) / Math.LN2 let ratio = 1 / (Math.pow(2, steps / 2) * OVERVIEWMAP.MIN_RATIO) this.scaleFromCenter(extent, ratio) ovview.fit(extent) } /** * 计算缩放 * @param extent * @param value */ ol.control.OverviewMapH.prototype.scaleFromCenter = function (extent, value) { let deltaX = ((extent[2] - extent[0]) / 2) * (value - 1) let deltaY = ((extent[3] - extent[1]) / 2) * (value - 1) extent[0] -= deltaX extent[2] += deltaX extent[1] -= deltaY extent[3] += deltaY } /** * 重新设置视图中心,将主视图的中心点设置为鹰眼的中心点 * @private */ ol.control.OverviewMapH.prototype.recenter_ = function () { let map = this.getMap() let ovmap = this.ovmap_ let view = map.getView() let ovview = ovmap.getView() ovview.setCenter(view.getCenter()) } /** * Update the box using the main map extent * @private */ ol.control.OverviewMapH.prototype.updateBox_ = function () { let map = this.getMap() let ovmap = this.ovmap_ let mapSize = /** @type {ol.Size} */ (map.getSize()) let view = map.getView() let ovview = ovmap.getView() let rotation = view.getRotation() let overlay = this.boxOverlay_ let box = this.boxOverlay_.getElement() let extent = view.calculateExtent(mapSize) let ovresolution = ovview.getResolution() let bottomLeft = ol.extent.getBottomLeft(extent) let topRight = ol.extent.getTopRight(extent) let rotateBottomLeft = this.calculateCoordinateRotate_(rotation, bottomLeft) overlay.setPosition(rotateBottomLeft) if (box) { box.style.width = Math.abs((bottomLeft[0] - topRight[0]) / ovresolution) + 'px' box.style.height = Math.abs((topRight[1] - bottomLeft[1]) / ovresolution) + 'px' } } /** * 计算坐标角度 * @param rotation * @param coordinate * @returns {*} * @private */ ol.control.OverviewMapH.prototype.calculateCoordinateRotate_ = function (rotation, coordinate) { let coordinateRotate let map = this.getMap() let view = map.getView() let currentCenter = view.getCenter() if (currentCenter) { coordinateRotate = [ coordinate[0] - currentCenter[0], coordinate[1] - currentCenter[1] ] ol.coordinate.rotate(coordinateRotate, rotation) ol.coordinate.add(coordinateRotate, currentCenter) } return coordinateRotate } /** * 处理点击事件 * @param event * @private */ ol.control.OverviewMapH.prototype.handleClick_ = function (event) { event.preventDefault() this.handleToggle_(event) } /** * @private */ ol.control.OverviewMapH.prototype.handleToggle_ = function (event) { if (this.collapsed_) { this.collapsed_ = false event.target.style.backgroundPosition = '-40px -405px' this.element.style.width = '17px' this.element.style.height = '17px' } else { this.collapsed_ = true event.target.style.backgroundPosition = '-40px -386px' this.element.style.width = '240px' this.element.style.height = '240px' } let ovmap = this.ovmap_ if (!this.collapsed_ && !ovmap) { ovmap.updateSize() this.resetExtent_() Events.listenOnce(ovmap, 'postrender', this.updateBox_, this) } } /** * 返回鹰眼是否可折叠 * @returns {*|boolean} */ ol.control.OverviewMapH.prototype.getCollapsible = function () { return this.collapsible_ } /** * 设置鹰眼是否可折叠 * @param collapsible */ ol.control.OverviewMapH.prototype.setCollapsible = function (collapsible) { if (this.collapsible_ === collapsible) { return } this.collapsible_ = collapsible if (!collapsible && this.collapsed_) { this.handleToggle_() } } /** * 设置鹰眼收起状态 * @param collapsed */ ol.control.OverviewMapH.prototype.setCollapsed = function (collapsed) { if (!this.collapsible_ || this.collapsed_ === collapsed) { return } this.handleToggle_() } /** * 判断鹰眼是否收起 * @returns {boolean|*} */ ol.control.OverviewMapH.prototype.getCollapsed = function () { return this.collapsed_ } /** * 返回当前鹰眼 * @returns {ol.Map} 返回鹰眼地图对象---- */ ol.control.OverviewMapH.prototype.getOverviewMap = function () { return this.ovmap_ } const olControlOverviewMap = ol.control.OverviewMapH export default olControlOverviewMap