UNPKG

ol-plot-enhanced

Version:
480 lines (442 loc) 11.6 kB
import { Map, Overlay } from 'ol' import { DragPan as $DragPan } from 'ol/interaction' import autosize from 'autosize' import { DEF_TEXT_STYEL } from '../../Constants' import { merge, bindAll } from '../../Utils/utils' import { on, off, hasClass, setStyle, getStyle } from '../../Utils/domUtils' class PlotTextBox extends Overlay { constructor (options = {}) { const [id, element, offset, stopEvent, positioning, insertFirst, autoPan, autoPanAnimation, autoPanMargin, className] = [ options['id'], options['element'], options['offset'], options['stopEvent'], options['positioning'], options['insertFirst'], options['autoPan'], options['autoPanAnimation'], options['autoPanMargin'], (options['className'] ? options['className'] : 'ol-plot-text-editor') ] super({ id, element, stopEvent, insertFirst, autoPan, autoPanAnimation, autoPanMargin, className }) this.setOffset(offset !== undefined ? offset : [0, 0]) this.setPositioning(positioning !== undefined ? positioning : 'center-center') /** * 地图交互 * @type {undefined} */ this.mapDragPan = undefined /** * is click * @type {boolean} * @private */ this.isClick_ = false /** * 是否处于拖拽状态 * @type {boolean} * @private */ this.dragging_ = false /** * 当前气泡是否获取焦点 * @type {boolean} * @private */ this.isFocus_ = false /** * 当前配置信息 * @type {{}} * @private */ this.options_ = options /** * 当前气泡位置 * @type {Array} * @private */ this._position = (options['position'] && options['position'].length > 0) ? options['position'] : [] /** * 防抖延时 * @type {null} * @private */ this.handleTimer_ = null /** * 每次鼠标按下的位置 * @type {Array} * @private */ this.currentPixel_ = [] bindAll([ 'handleFocus_', 'handleBlur_', 'handleClick_', 'handleDragStart_', 'handleDragEnd_', 'handleDragDrag_', 'closeCurrentPlotText', 'handleResizeMouseDown_', 'handleResizeMouseMove_', 'handleResizeMouseUp_', 'resizeButtonMoveHandler_' ], this) /** * 创建text content */ this.createTextContent(options) } /** * 创建文本框父容器 * @param options */ createTextContent (options) { const _className = options.className || 'ol-plot-text-editor' const content = document.createElement('textarea') content.className = _className content.style.width = options['width'] + 'px' content.style.height = options['height'] + 'px' content.style.minHeight = options['minHeight'] + 'px' content.setAttribute('id', options['id']) content.setAttribute('autofocus', true) autosize(content) on(content, 'focus', this.handleFocus_) on(content, 'blur', this.handleBlur_) on(content, 'click', this.handleClick_) on(content, 'mousedown', this.handleDragStart_) on(window, 'mouseup', this.handleDragEnd_) this.set('isPlotText', true) this.setElement(content) this.createCloseButton(options) this.createResizeButton(options) this.setPosition(this._position) this.dispatchEvent('textBoxDrawEnd', { overlay: this, element: content, uuid: options['id'] }) } /** * 获取文本框 * @returns {string} * @private */ getTextAreaFromContent_ () { let _node = '' const childrens_ = Array.prototype.slice.call((this.element && this.element.children), 0) if (childrens_.length > 0) { childrens_.every(ele => { if (ele.nodeType === 1 && ele.nodeName.toLowerCase() === 'textarea') { _node = ele return false } else { return true } }) } return _node } /** * 创建关闭按钮 * @param options */ createCloseButton (options) { const _closeSpan = document.createElement('span') _closeSpan.className = 'ol-plot-text-editor-close' _closeSpan.setAttribute('data-id', options['id']) off(_closeSpan, 'click', this.closeCurrentPlotText) on(_closeSpan, 'click', this.closeCurrentPlotText) this.element.appendChild(_closeSpan) } /** * 创建文本框大小调整按钮 * @param options */ createResizeButton (options) { const _resizeSpan = document.createElement('span') _resizeSpan.className = 'ol-plot-text-editor-resize' _resizeSpan.setAttribute('data-id', options['id']) off(_resizeSpan, 'mousedown', this.handleResizeMouseDown_) off(_resizeSpan, 'mousemove', this.handleResizeMouseMove_) on(_resizeSpan, 'mousedown', this.handleResizeMouseDown_) on(_resizeSpan, 'mousemove', this.handleResizeMouseMove_) this.element.appendChild(_resizeSpan) } /** * 调整大小 * @param event * @private */ resizeButtonMoveHandler_ (event) { const pixel_ = event.pixel const element_ = this.getTextAreaFromContent_() if (pixel_.length < 1 || this.currentPixel_.length < 1 || !element_) return const _offset = [pixel_[0] - this.currentPixel_[0], pixel_[1] - this.currentPixel_[1]] const _size = [element_.offsetWidth, element_.offsetHeight] const _width = _size[0] + _offset[0] * 2 const _height = _size[1] + _offset[1] * 2 setStyle(element_, 'width', _width + 'px') setStyle(element_, 'height', _height + 'px') this.currentPixel_ = pixel_ this.getMap().render() } /** * 处理移动事件 * @param event * @private */ handleResizeMouseMove_ (event) { event.stopImmediatePropagation() } /** * 处理鼠标按下事件 * @param event * @private */ handleResizeMouseDown_ (event) { if (!this.getMap()) return this.currentPixel_ = [event.x, event.y] this.getMap().on('pointermove', this.resizeButtonMoveHandler_) on(this.getMap().getViewport(), 'mouseup', this.handleResizeMouseUp_) } /** * 处理鼠标抬起事件,移除所有事件监听 * @param event * @private */ handleResizeMouseUp_ (event) { if (!this.getMap()) return this.getMap().un('pointermove', this.resizeButtonMoveHandler_) off(this.getMap().getViewport(), 'mouseup', this.handleResizeMouseUp_) this.currentPixel_ = [] } /** * 处理关闭事件 * @param event */ closeCurrentPlotText (event) { if (!this.getMap()) return if (event && hasClass(event.target, 'ol-plot-text-editor-close')) { let _id = event.target.getAttribute('data-id') if (_id) { const _overlay = this.getMap().getOverlayById(_id) if (_overlay) { this.getMap().removeOverlay(_overlay) } } } } /** * 处理获取焦点事件 * @private */ handleFocus_ () { this.isFocus_ = true if (this.getMap()) { this.getMap().set('activeTextArea', this) this.getMap().dispatchEvent('activeTextArea') } } /** * 处理失去焦点事件 * @private */ handleBlur_ () { this.isFocus_ = false if (this.getMap()) { this.getMap().set('activeTextArea', null) this.getMap().set('disActiveTextArea', this) this.getMap().dispatchEvent('disActiveTextArea') } } /** * 处理拖拽开始 * @private */ handleDragStart_ (event) { if (!this.getMap()) return if (!this.dragging_ && this.isMoveModel() && this.isFocus_) { this.handleTimer_ = window.setTimeout(() => { window.clearTimeout(this.handleTimer_) this.handleTimer_ = null if (!this.isClick_) { this.dragging_ = true this.disableMapDragPan() this.preCursor_ = this.element.style.cursor on(this.getMap().getViewport(), 'mousemove', this.handleDragDrag_) on(this.element, 'mouseup', this.handleDragEnd_) } }, 300) } } /** * 处理拖拽 * @param event * @private */ handleDragDrag_ (event) { if (this.dragging_) { this.element.style.cursor = 'move' this._position = this.getMap().getCoordinateFromPixel([event.clientX, event.clientY]) this.setPosition(this._position) } } /** * 处理拖拽 * @private */ handleDragEnd_ (event) { this.isClick_ = false window.clearTimeout(this.handleTimer_) this.handleTimer_ = null if (this.dragging_ && this.isFocus_) { this.dragging_ = false this.enableMapDragPan() this.element.style.cursor = this.preCursor_ off(this.getMap().getViewport(), 'mousemove', this.handleDragDrag_) off(this.element, 'mouseup', this.handleDragEnd_) } } /** * 处理点击事件 * @param event * @private */ handleClick_ (event) { if (event.target === this.element) { this.isClick_ = true } else { this.isClick_ = false } } /** * 是否处于选择模式 * @returns {boolean} */ isMoveModel () { const range = window.getSelection().getRangeAt(0) return range.collapsed } /** * 设置样式 * @param style */ setStyle (style = {}) { const _element = this.getTextAreaFromContent_() if (_element) { for (let key in style) { if (style[key]) { setStyle(_element, key, style[key]) } } } } /** * 获取当前样式 * @returns {CSSStyleDeclaration} */ getStyle () { const _style = {} const _element = this.getTextAreaFromContent_() if (_element) { for (let key in DEF_TEXT_STYEL) { _style[key] = getStyle(_element, key) } } return _style } /** * set value * @param value */ setValue (value) { const _element = this.getTextAreaFromContent_() if (_element) { _element.value = value if (value) { autosize.update(_element) } this.getMap().render() } } /** * get value * @returns {*} */ getValue () { const _element = this.getTextAreaFromContent_() if (_element) { return _element.value } else { return '' } } /** * 获取宽度 * @returns {number} */ getWidth () { const element_ = this.getTextAreaFromContent_() if (element_ && element_.offsetWidth) { return element_.offsetWidth } else { return 0 } } /** * 获取高度 * @returns {number} */ getHeight () { const element_ = this.getTextAreaFromContent_() if (element_ && element_.offsetHeight) { return element_.offsetHeight } else { return 0 } } /** * 激活地图的拖拽平移 */ enableMapDragPan () { const _map = this.getMap() if (!_map) return if (this.mapDragPan && this.mapDragPan instanceof $DragPan) { _map.addInteraction(this.mapDragPan) delete this.mapDragPan } } /** * 禁止地图的拖拽平移 */ disableMapDragPan () { const _map = this.getMap() if (!_map) return let interactions = _map.getInteractions().getArray() interactions.every(item => { if (item instanceof $DragPan) { this.mapDragPan = item _map.removeInteraction(item) return false } else { return true } }) } /** * set map * @param map */ setMap (map) { super.setMap(map) if (map && map instanceof Map) { this.setStyle(merge(DEF_TEXT_STYEL, this.options_['style'])) this.setValue(this.options_['value']) } } } export default PlotTextBox