UNPKG

@mapgis/webclient-leaflet-plugin

Version:

666 lines (607 loc) 24.5 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title> view/utils/Popup.js</title> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link type="text/css" rel="stylesheet" href="styles/app.min.css"> <link type="text/css" rel="stylesheet" href="styles/iframe.css"> <link type="text/css" rel="stylesheet" href=""> </head> <body class="layout small-header"> <div id="stickyNavbarOverlay"></div> <div class="top-nav"> <div class="inner"> <a id="hamburger" role="button" class="navbar-burger" aria-label="menu" aria-expanded="false"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> <div class="logo"> <h1> MapGIS Client for JavaScript API</h1> </div> <div class="menu"> <div class="navigation"> <a class="link user-link " href="/docs/cesium/index.html" > Cesium </a> <a class="link user-link " href="/docs/mapboxgl/index.html" > MapboxGL </a> <a class="link user-link " href="/docs/leaflet/index.html" > Leaflet </a> <a class="link user-link " href="/docs/openlayers/index.html" > OpenLayers </a> </div> </div> </div> </div> <div id="main"> <div class="sidebar " id="sidebarNav" > <div> <span class="mapgis-api-document-span"><a href="index.html">API文档</a></span> </div> <div class="search-wrapper"> <input id="search" type="text" placeholder="搜索文档..." class="input"> </div> <nav> <div class="category"><div style="font-weight: bold;vertical-align: middle;padding: 0.4rem 0;" class="mapgis-menu-span"><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/m.png" alt="">视图模块</div><ul class="mapgis-sidebar-menus"><li><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/c.png" alt=""><a href="DrawControl.html">DrawControl</a><span style="display: none;"><p>绘制工具</p></span></li><li><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/c.png" alt=""><a href="MapView.html">MapView</a><span style="display: none;"><p>二维场景视图(leaflet引擎),对地图引擎进行管理,如果要对地图图层进行管理请参考[Map]{@link Map},<br/> 参考示例: <a href='#MapView'>[初始化二维场景视图]</a> <br>[ES5引入方式]:<br/> Zondy.MapView() <br/> [ES6引入方式]:<br/> import { MapView } from '@mapgis/webclient-leaflet-plugin' <br/></p></span></li><li><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/c.png" alt=""><a href="Popup.html">Popup</a><span style="display: none;"><p>二维场景信息弹窗(leaflet引擎) 参考示例: <a href='#MapView'>[初始化二维场景视图]</a> [ES6引入方式]:<br/> import { Popup } from '@mapgis/webclient-leaflet-plugin' <br/> 自定义样式说明:<br/> zondy-popup__content 弹窗容器样式<br/> zondy-popup__tip 弹窗对话框箭头样式<br/> zondy-popup__header 弹窗头部样式<br/> zondy-popup__content 弹窗主体样式<br/> zondy-popup__footer 弹窗底部样式<br/></p></span></li><li><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/c.png" alt=""><a href="Screenshot.html">Screenshot</a><span style="display: none;"><p>屏幕打印工具</p></span></li></ul><div style="font-weight: bold;vertical-align: middle;padding: 0.4rem 0;" class="mapgis-menu-span"><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/m.png" alt="">草图编辑模块</div><ul class="mapgis-sidebar-menus"><li><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/c.png" alt=""><a href="SketchEditorLeaflet.html">SketchEditorLeaflet</a><span style="display: none;"><p>二维场景草图编辑类<br/> <br>[ES5引入方式]:<br/> const { SketchEditorLeaflet } = Zondy <br/> [ES6引入方式]:<br/> import { SketchEditorLeaflet } from &quot;@mapgis/webclient-leaflet-plugin&quot; <br/></p></span></li></ul><div style="font-weight: bold;vertical-align: middle;padding: 0.4rem 0;" class="mapgis-menu-span"><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/m.png" alt="">渲染器模块</div><ul class="mapgis-sidebar-menus"><li><img style="width: 20px;margin-right: 6px;vertical-align: middle;" src="./styles/c.png" alt=""><a href="Zondy.ThemeLayer.GraphThemeLayer.html">GraphThemeLayer</a><span style="display: none;"><p>统计专题图通过为每个要素绘制统计图表来反映其对应的专题值的大小。它可同时表示多个字段属性信息,在区域本身与各区域之间形成横向和纵向的对比。<br>统计专题图多用于具有相关数量特征的地图上,比如表示不同地区多年的粮食产量、GDP、人口等,不同时段客运量、地铁流量等。目前提供的统计图类型有:柱状图(Bar),折线图(Line),饼图(Pie),三维柱状图(Bar3D),点状图(Point),环状图(Ring)。</p></span></li></ul></div> </nav> </div> <div class="core" id="main-content-wrapper"> <div class="content"> <header id="page-title" class="page-title"> <span class="page-title-main">类名</span> <span class="page-title-sub">view/utils/Popup.js</span> </header> <section> <article> <pre class="prettyprint source linenums"><code>import { defaultValue, Evented, Log } from '@mapgis/webclient-common' import * as L from '@mapgis/leaflet' /** * 二维场景信息弹窗(leaflet引擎) * 参考示例: * &lt;a href='#MapView'>[初始化二维场景视图]&lt;/a> * [ES6引入方式]:&lt;br/> * import { Popup } from '@mapgis/webclient-leaflet-plugin' &lt;br/> * 自定义样式说明:&lt;br/> * zondy-popup__content 弹窗容器样式&lt;br/> * zondy-popup__tip 弹窗对话框箭头样式&lt;br/> * zondy-popup__header 弹窗头部样式&lt;br/> * zondy-popup__content 弹窗主体样式&lt;br/> * zondy-popup__footer 弹窗底部样式&lt;br/> * @class Popup * @moduleEX ViewModule * @param {Object} options 构造参数 * @param {MapView} [options.view] 弹窗地图视图对象 * @param {String} [options.id] 弹窗ID * @param {Point} [options.location] 弹窗定位点 * @param {String} [options.title] 弹窗标题 * @param {String|HTMLElement} [options.content] 弹框内容 * @param {String} [options.alignment] 弹框方位,值为"auto"或"bottom-left"或"top-center"或"top-right"或"bottom-left"或"bottom-center"或"bottom-right"。 * @param {Array} [options.defaultButtons] 弹框内容,可选数组项有'toggle','close','zoom'。toggle:收缩主题内容按钮;close:关闭按钮;zoom:缩放按钮。 * * @example &lt;caption>&lt;h7 id='Popup'>打开视图弹窗&lt;/h7>&lt;/caption> * // ES5引入方式 * const { Map, MapView } = Zondy * // ES6引入方式 * import { Map, MapView } from "@mapgis/webclient-leaflet-plugin" * // 初始化图层管理容器 * const map = new Map(); * // 初始化地图视图对象 * const mapView = new MapView({ * // 二维场景视图的容器(html的div标签)ID * viewId: "二维场景视图的容器的id", * // 图层管理容器 * map: map * }); * const popupObj = { * title: "标题", * content:"弹出窗口主题内容,详细内容", * location: new Point({coordinates:[123,34]}), * alignment: "bottom-center" *} * mapView.popup.open(popupObj) * mapView.popup.close(popupObj) * &lt;style> * .zondy-popup__container{ * background-color: #40a9ff; * margin: 0 * } * .zondy-popup__tip{ * // display: none; * background-color: #ffffff; * } * .zondy-popup__header{ * background-color: #40a9ff; * } * .zondy-popup__content{ * background-color: #ffffff; * } * .zondy-popup__footer{ * // display: none; * background-color: #40a9ff; * } * &lt;/style> */ class Popup extends Evented { constructor(options) { super(options) /** * 弹框的地图视野 * @member {MapView} */ this.view = defaultValue(options.view, null) // /** // * 弹框唯一id // * @member {String} // */ // this.id = this._id /** * 弹框位置 * @member {String} */ this.location = defaultValue(options.location, '') /** * 弹框标题 * @member {String} */ this.title = defaultValue(options.title, '') /** * 弹框内容 * @member {String} */ this.content = defaultValue(options.content, '') // /** // * 弹框按钮事件 // * @member {String} // */ // this.action = undefined /** * 弹框方位,值为"auto"|"bottom-left"|"top-center"|"top-right"|"bottom-left"|"bottom-center"|"bottom-right" * @member {String} */ this.alignment = defaultValue(options.alignment, 'bottom-center') /** * 默认按钮 ['toggle','close','zoom'] * @member {Array} */ this.defaultButtons = defaultValue(options.defaultButtons, [ 'toggle', 'close', 'zoom' ]) this._popup = undefined // 初始化弹窗 this._initPopup() // 设置popup自定义class样式 this._initDefaultClass() } /** * 初始化弹窗 * @private * */ _initPopup() { this._customPopup() // 关闭地图点击关闭弹窗事件 this.view._innerView.closePopupOnClick = false } /** * 自定义弹窗样式,修改leaflet默认样式 * @private * */ _customPopup() { L.CustomPopup = L.Popup.extend({ _initLayout() { const prefix = 'leaflet-popup' const container = L.DomUtil.create( 'div', `${prefix} ${this.options.className || ''} leaflet-zoom-animated` ) this._container = container container.setAttribute('style', 'margin: 0;') // if (this.options.closeButton) { // const closeButton = L.DomUtil.create( // 'a', // `${prefix}-close-button`, // container // ) // this._closeButton = closeButton // closeButton.href = '#close' // closeButton.innerHTML = '&amp;#215;' // closeButton.setAttribute('style', 'top:12px;right:8px') // // L.DomEvent.on(closeButton, 'click', this._onCloseButtonClick, this) // } const wrapper = L.DomUtil.create( 'div', `zondy-popup__container ${prefix}-content-wrapper`, container ) this._wrapper = wrapper this._contentNode = L.DomUtil.create( 'div', `${prefix}-content`, wrapper ) this._contentNode.setAttribute('style', 'margin:0') L.DomEvent.disableClickPropagation(wrapper) .disableScrollPropagation(this._contentNode) .on(wrapper, 'contextmenu', L.DomEvent.stopPropagation) // this._tipContainer = L.DomUtil.create( // 'div', // `${prefix}-tip-container`, // container // ) // this._tip = L.DomUtil.create('div', `zondy-popup__tip ${prefix}-tip`, this._tipContainer) this._tipContainer = L.DomUtil.create('div', '', container) this._tipContainer.setAttribute( 'style', 'margin: auto;width: 40px;height: 20px;pointer-events: none;overflow: hidden;pointer-events: none;' ) this._tip = L.DomUtil.create( 'div', `zondy-popup__tip ${prefix}-tip`, this._tipContainer ) } }) } /** * 初始化弹窗默认面板 * @private * */ _contentUI(title, content) { const self = this let defaultUI = undefined const string2Dom = function (arg) { const objE = document.createElement('div') objE.innerHTML = arg return objE.childNodes } defaultUI = document.createElement('div') defaultUI.setAttribute('id', `${this.id}-popup-default`) // 构建头部DOM const headerDom = document.createElement('div') headerDom.setAttribute('class', 'zondy-popup__header') headerDom.setAttribute('style', 'display: flex;') // 收缩按钮 const toggleDom = string2Dom(`&lt;div class="zondy-popup__toggle"> &lt;svg aria-hidden="true" class="svg" fill="currentColor" height="16px" width="16px" viewBox="0 0 24 24" width="100%" xmlns="http://www.w3.org/2000/svg">&lt;path d="M5 13.793l7-7 7 7v1.414l-7-7-7 7z">&lt;/path>&lt;/svg> &lt;/div>`)[0] // 关闭按钮 const closeDom = string2Dom(`&lt;div class="zondy-popup__close"> &lt;svg aria-hidden="true" class="svg" fill="currentColor" height="16px" width="16px" viewBox="0 0 16 16" width="100%" xmlns="http://www.w3.org/2000/svg">&lt;path d="M3.98 11.303L7.281 8 3.98 4.697l.707-.707L7.99 7.293l.01-.01.01.01 3.304-3.303.707.707L8.718 8l3.303 3.303-.707.707L8.01 8.707l-.01.01-.01-.01-3.304 3.303z">&lt;/path>&lt;/svg> &lt;/div>`)[0] if (title) { const titleDom = string2Dom( `&lt;div class="zondy-popup__title" style="flex: 1;">&lt;/div>` )[0] headerDom.appendChild(titleDom) if (typeof title === 'object') { if (title instanceof Node) { titleDom.appendChild(title) } else if (title instanceof NodeList) { title.forEach((dom) => { titleDom.appendChild(dom) }) } } else { titleDom.innerHTML = title } if (this.defaultButtons.indexOf('toggle') > -1) { headerDom.appendChild(toggleDom) // 收缩按钮事件 let showContentFlag = true headerDom.onclick = function () { showContentFlag = !showContentFlag if (showContentFlag) { document .getElementById(`${self.id}-popup-default`) .querySelector('.zondy-popup__content').style.display = 'block' } else { document .getElementById(`${self.id}-popup-default`) .querySelector('.zondy-popup__content').style.display = 'none' } } } if (this.defaultButtons.indexOf('close') > -1) { headerDom.appendChild(closeDom) // 关闭按钮事件 closeDom.onclick = () => { this.close() } } } // 构建中间内容DOM const contentDom = document.createElement('div') contentDom.setAttribute('class', 'zondy-popup__content') if (content) { if (typeof content === 'object') { if (content instanceof Node) { contentDom.appendChild(content) } else if (content instanceof NodeList) { // content.forEach((dom)=>{ // contentDom.appendChild(dom) // }) for (let i = 0; i &lt; content.length; i++) { contentDom.appendChild(content[i]) i-- } } } else { contentDom.innerHTML = content } } // 构建底部页脚DOM const footerDom = document.createElement('div') footerDom.setAttribute('class', 'zondy-popup__footer') // 缩放按钮 const zoomDom = string2Dom(`&lt;div class="zondy-popup__zoom" style="display: inline-block;width: 36px;height: 36px;line-height: 36px;text-align: center;"> &lt;svg class="svg" fill="currentColor" height="16px" width="16px" viewBox="0 0 16 16" width="100%" xmlns="http://www.w3.org/2000/svg">&lt;path d="M9 7H7v2H6V7H4V6h2V4h1v2h2zm6.805 7.861l-.943.942a.665.665 0 0 1-.943 0l-3.067-3.067a.667.667 0 0 1 0-.943l.129-.13-1.108-1.107A5.279 5.279 0 1 1 11.8 6.5a5.251 5.251 0 0 1-1.237 3.366l1.108 1.108.124-.124a.668.668 0 0 1 .943 0l3.067 3.068a.666.666 0 0 1 0 .943zM10.8 6.5a4.3 4.3 0 1 0-4.3 4.3 4.304 4.304 0 0 0 4.3-4.3zm4.062 7.89l-2.595-2.598-.473.473 2.597 2.595z">&lt;/path>&lt;/svg> &lt;/div>`)[0] if (this.defaultButtons.indexOf('zoom') > -1) { footerDom.appendChild(zoomDom) // 缩放按钮事件 zoomDom.onclick = function () { self.view.flyTo({ zoom: self.view._zoom + 1, center: self.location }) } } // footer有子节点,增加分割线样式 if (footerDom.childNodes.length > 0) { footerDom.setAttribute( 'class', 'zondy-popup__footer zondy-popup__footer-division' ) } defaultUI.appendChild(headerDom) defaultUI.appendChild(contentDom) defaultUI.appendChild(footerDom) // // tip三角 // const tipDom = document.createElement('div') // tipDom.setAttribute('style', 'width: 40px;height: 20px;position: absolute;left: 50%;margin-top: -1px;margin-left: -20px;overflow: hidden;pointer-events: none;bottom: -3px;') // tipDom.innerHTML = `&lt;div class='zondy-popup__tip' style='width: 17px;height: 17px;padding: 1px;margin: -10px auto 0;pointer-events: auto;transform: rotate(45deg);'> // &lt;/div>` // defaultUI.appendChild(tipDom) return defaultUI } /** * 设置popup自定义class样式 * @private */ _initDefaultClass() { const styleDomString = ` .zondy-popup__container{background-color: #fff;padding:0;border-radius: 10px;} .zondy-popup__tip{ background-color: #fff; } .zondy-popup__header{ padding: 8px; font-size: 18px; font-weight: 600; line-height: 20px; border-top-left-radius: 10px; border-top-right-radius: 10px; } .zondy-popup__content{ padding: 8px; } .zondy-popup__footer{ } .zondy-popup__footer-division{ border-top: 1px solid; } .zondy-popup__toggle,.zondy-popup__close{ display: inline-block;width: 30px;text-align: center; } ` let styleExist = false const styles = document.head.getElementsByTagName('style') if (styles) { for (let i = 0; i &lt; styles.length; i++) { if (styles[i].innerHTML.indexOf('styleDomString') > -1) { styleExist = true break } } } if (!styleExist) { const styleDom = document.createElement('style') styleDom.innerHTML = styleDomString document.querySelector('head').append(styleDom) } } /** * 打开popup弹窗 * @param {Object} options 弹窗属性对象 * */ open(options) { if (this._popup) { this.close() this._popup = undefined this.openPopup(options) } else { this.openPopup(options) } } /** * 打开popup弹窗 * @param {Object} options 弹窗属性对象 * */ openPopup(options) { const self = this this.view = options.view ? options.view : this.view this.location = options.location ? options.location : this.location this.title = options.title ? options.title : this.title this.content = options.content ? options.content : this.content this.alignment = options.alignment ? options.alignment : this.alignment if (!this.view._innerView) { Log.info('没有视图引擎!') return } const latlng = L.latLng( this.location.coordinates[1], this.location.coordinates[0] ) const content = this._contentUI(this.title, this.content) this._popup = new L.CustomPopup({ className: 'layerPopup', // autoClose: false, maxWidth: 1900, minWidth: 50, closeOnClick: false }) .setLatLng(latlng) .setContent(content) .openOn(this.view._innerView) // this._popup = L.popup().setLatLng(latlng).setContent(content).openOn(this.view) const offset = this._getOffset() this._popup = new L.CustomPopup({ className: 'layerPopup', // autoClose: false, maxWidth: 1900, minWidth: 50, closeOnClick: false, offset }) .setLatLng(latlng) .setContent(content) .openOn(this.view._innerView) } /** * 获取偏移对象 * @private */ _getOffset() { let offset = null if (this._popup &amp;&amp; this._popup._container) { if (this.alignment) { const rect = this._popup._container.getBoundingClientRect() const offsetXY = this._getOffsetByAlignment( this.alignment, rect.width, rect.height ) offset = new L.Point(offsetXY.x, offsetXY.y) } } return offset } /** * 将锚点位置转换成x、y方向偏移量 * @private */ _getOffsetByAlignment(alignment, width, height) { let offsetX = 0 let offsetY = 0 switch (alignment) { case 'top-left': offsetX = width / 2 offsetY = height break case 'top-center': offsetY = height break case 'top-right': offsetX = -width / 2 offsetY = height break case 'bottom-left': offsetX = width / 2 break case 'auto': case 'bottom-center': break case 'bottom-right': offsetX = -width / 2 break default: break } return { x: offsetX, y: offsetY } } /** * 关闭popup弹窗 * */ close() { if (this.view._innerView) { this.view._innerView.closePopup(this._popup) } } destroy() {} } export default Popup </code></pre> </article> </section> </div> <footer class="footer"> <div class="content has-text-centered"> <p>文档生成<a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.6.11</a></p> <p class="sidebar-created-by"> <a href="http://www.smaryun.com" target="_blank">司马云</a> <span>© 2023 云生态圈</span> <a href="http://192.168.82.89:8086/#/index" target="_blank">MapGIS Client for JavaScript</a> </p> </div> </footer> </div> <div id="side-nav" class="side-nav"> <div style="margin-bottom: 10px;"> <img style="vertical-align: middle;margin-right: 10px;width: 30px;" src="./styles/anchor.png"/><a href="#page-title">构造函数</a> </div> <div style="margin-bottom: 10px;"> <img style="vertical-align: middle;margin-right: 10px;width: 30px;" src="./styles/anchor.png"/><a href="#member">成员变量</a> </div> <div style="margin-bottom: 10px;"> <img style="vertical-align: middle;margin-right: 10px;width: 30px;" src="./styles/anchor.png"/><a href="#function">方法</a> </div> <div> <img style="vertical-align: middle;margin-right: 10px;width: 30px;" src="./styles/anchor.png"/><a href="#event">事件</a> </div> </div> </div> <script src="scripts/linenumber.js"> </script> <script src="scripts/search.js"> </script> </body> </html>