@mapgis/webclient-leaflet-plugin
Version: 
698 lines (612 loc) • 23.8 kB
HTML
<!DOCTYPE html>
<html lang="en">
<head>
  
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title> document/theme/ThemeLayer.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]{ 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 "/webclient-leaflet-plugin" <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">document/theme/ThemeLayer.js</span>
                </header>
                
    
    <section>
        <article>
            <pre class="prettyprint source linenums"><code>import { Zondy } from '@mapgis/webclient-common'
import * as L from '@mapgis/leaflet'
// eslint-disable-next-line import/no-extraneous-dependencies
import { LevelRenderer, modifyDOMElement } from '@mapgis/webclient-graphic-render'
/**
 * @class Zondy.ThemeLayer.ThemeLayer
 * @classdesc 专题图层基类,调用建议使用其子类实现类。
 * @extends {L.Layer}
 * @param {string} name - 专题图图层名称。
 * @param {Object} options - 可选参数。
 * @param {string} [options.id] - 专题图层 ID。默认使用 CommonUtil.createUniqueID("themeLayer_") 创建专题图层 ID。
 * @param {number} [options.opacity=1] - 图层透明度。
 * @fires Zondy.ThemeLayer.ThemeLayer#featuresremoved
 */
const ThemeLayer = L.Layer.extend({
  options: {
    name: null,
    opacity: 1,
    // {Array} 专题要素事件临时存储,临时保存图层未添加到 map 前用户添加的事件监听,待图层添加到 map 后把这些事件监听添加到图层上,清空此图层。
    // 这是一个二维数组,组成二维数组的每个一维数组长度为 2,分别是 event, callback。
    TFEvents: null
  },
  initialize(name, options) {
    L.Util.setOptions(this, options)
    this.options.name = name
    this.features = []
    this.TFEvents = options && options.TFEvents ? options.TFEvents : []
    this.levelRenderer = new LevelRenderer()
    this.movingOffset = [0, 0]
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.getEvents
   * @description 获取图层事件。
   * @returns {Object} 返回图层支持的事件。
   */
  getEvents() {
    const me = this
    const events = {
      zoomend: me._reset,
      moveend: me._reset,
      resize: me._resize
    }
    if (this._map._zoomAnimated) {
      events.zoomanim = me._zoomAnim
    }
    return events
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.onRemove
   * @description 删除某个地图。
   * @param {L.Map} map - 要删除的地图。
   */
  onRemove(map) {
    const me = this
    L.DomUtil.remove(me.container)
    map.off('mousemove', me.mouseMoveHandler)
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.onAdd
   * @description 添加专题图。
   * @param {L.Map} map - 要添加的地图。
   * @private
   */
  onAdd(map) {
    const me = this
    me.map = me._map = map
    me._initContainer()
    if (!me.levelRenderer) {
      map.removeLayer(me)
      return
    }
    // 初始化渲染器
    const size = map.getSize()
    me.container.style.width = `${size.x}px`
    me.container.style.height = `${size.y}px`
    me._updateOpacity()
    me.renderer = me.levelRenderer.init(me.container)
    me.renderer.clear()
    if (me.features && me.features.length > 0) {
      me._reset()
    }
    // 处理用户预先(在图层添加到 map 前)监听的事件
    me.addTFEvents()
    me.mouseMoveHandler = function (e) {
      const xy = e.layerPoint
      me.currentMousePosition = L.point(
        xy.x + me.movingOffset[0],
        xy.y + me.movingOffset[1]
      )
    }
    map.on('mousemove', me.mouseMoveHandler)
    me.update()
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.addFeatures
   * @description 向专题图图层中添加数据。
   * @param {Object} features - 待转要素。
   */
  addFeatures(features) {
    // eslint-disable-line no-unused-vars
    // 子类实现此方法
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.redrawThematicFeatures
   * @description 抽象方法,可实例化子类必须实现此方法。
   * @param {L.bounds} bounds - 重绘专题要素范围。
   */
  redrawThematicFeatures(bounds) {
    // eslint-disable-line no-unused-vars
    // 子类必须实现此方法
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.destroyFeatures
   * @description 销毁要素。
   * @param {Array.<Zondy.Feature.Vector>} features - 将被销毁的要素。
   */
  destroyFeatures(features) {
    if (features === undefined) {
      features = this.features
    }
    if (!features) {
      return
    }
    this.removeFeatures(features)
    for (let i = features.length - 1; i >= 0; i--) {
      features[i].destroy()
    }
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.removeFeatures
   * @description 从专题图中删除 feature。这个函数删除所有传递进来的矢量要素。
   * @param {Array.<Zondy.Feature.Vector>} features - 将被删除的要素。
   */
  removeFeatures(features) {
    const me = this
    if (!features || features.length === 0) {
      return
    }
    if (features === me.features) {
      return me.removeAllFeatures()
    }
    if (!L.Util.isArray(features)) {
      features = [features]
    }
    const featuresFailRemoved = []
    for (let i = features.length - 1; i >= 0; i--) {
      var feature = features[i]
      // 如果我们传入的feature在features数组中没有的话,则不进行删除,
      // 并将其放入未删除的数组中。
      const findex = L.Util.indexOf(me.features, feature)
      if (findex === -1) {
        featuresFailRemoved.push(feature)
        continue
      }
      me.features.splice(findex, 1)
    }
    const drawFeatures = []
    for (let hex = 0, len = me.features.length; hex < len; hex++) {
      feature = me.features[hex]
      drawFeatures.push(feature)
    }
    me.features = []
    me.addFeatures(drawFeatures)
    // 绘制专题要素
    if (me.renderer) {
      if (me._map) {
        me.redrawThematicFeatures(me._map.getBounds())
      } else {
        me.redrawThematicFeatures()
      }
    }
    const succeed = featuresFailRemoved.length === 0
    /**
     * @event Zondy.ThemeLayer.ThemeLayer#featuresremoved
     * @description 删除的要素成功之后触发。
     * @property {Array.<Zondy.Feature.Vector>} features - 事件对象。
     * @property {boolean} succeed - 要输是否删除成功,true 为删除成功,false 为删除失败。
     */
    me.fire('featuresremoved', {
      features: featuresFailRemoved,
      succeed
    })
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.removeAllFeatures
   * @description 清除当前图层所有的矢量要素。
   */
  removeAllFeatures() {
    const me = this
    if (me.renderer) {
      me.renderer.clear()
    }
    me.features = []
    me.fire('featuresremoved', {
      features: [],
      succeed: true
    })
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.getFeatures
   * @description 查看当前图层中的有效数据。
   * @returns {Array} 返回图层中的有效数据。
   */
  getFeatures() {
    const me = this
    const len = me.features.length
    const clonedFeatures = new Array(len)
    for (let i = 0; i < len; ++i) {
      clonedFeatures[i] = me.features[i]
    }
    return clonedFeatures
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.getFeatureBy
   * @description 在专题图的要素数组 features 里面遍历每一个 feature,当 feature[property] === value 时,返回此 feature(并且只返回第一个)。
   * @param {string} property - 要的某个属性名。
   * @param {string} value - 对应属性名得值。
   */
  getFeatureBy(property, value) {
    const me = this
    return me.features.find((feature) => {
      const attributes = feature.attributes
      if (feature[property] === value || attributes[property] === value) {
        return feature
      }
    })
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.getFeatureById
   * @description 通过给定一个 ID,返回对应的矢量要素,如果不存在则返回 null。
   * @param {number} featureId - 要素 ID。
   */
  getFeatureById(featureId) {
    return this.getFeatureBy('id', featureId)
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.getFeaturesByAttribute
   * @description 通过给定一个属性的 key 值和 value 值,返回所有匹配的要素数组。
   * @param {string} attrName - key 值。
   * @param {string} attrValue - value 值。
   * @returns {Array} 返回所有匹配的要素数组。
   */
  getFeaturesByAttribute(attrName, attrValue) {
    const me = this
    let feature
    const foundFeatures = []
    for (const id in me.features) {
      feature = me.features[id]
      if (
        feature &&
        feature.attributes &&
        feature.attributes[attrName] === attrValue
      ) {
        foundFeatures.push(feature)
      }
    }
    return foundFeatures
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.update
   * @description 更新图层。
   * @param {L.bounds} bounds - 图层范围。
   */
  update(bounds) {
    const mapOffset = this._map.containerPointToLayerPoint([0, 0])
    L.DomUtil.setPosition(this.container, mapOffset)
    const me = this
    //  var bounds = me._map.getBounds();
    //  var topLeft = me._map.latLngToLayerPoint(bounds.getNorthWest());
    //  var mapOffset = [parseInt(topLeft.x, 10) || 0, parseInt(topLeft.y, 10) || 0]
    // // var offsetLeft = parseInt(me._map.getContainer().style.left, 10);
    // // offsetLeft = -Math.round(offsetLeft);
    //  //var offsetTop = parseInt(me._map.getContainer().style.top, 10);
    //  //offsetTop = -Math.round(offsetTop);
    //  me.container.style.left = mapOffset[0] + 'px';
    //  me.container.style.top = mapOffset[1] + 'px';
    // 绘制专题要素
    if (me.renderer) {
      me.redrawThematicFeatures(bounds)
    }
    if (me.currentMousePosition) {
      me.currentMousePosition = L.point(
        me.currentMousePosition.x - me.movingOffset[0],
        me.currentMousePosition.y - me.movingOffset[1]
      )
    }
    me.movingOffset = [0, 0]
    me._zoom = me._map.getZoom()
    me._center = me._map.getCenter()
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.setOpacity
   * @description 设置图层的不透明度,取值 [0-1] 之间。
   * @param {number} opacity - 不透明度。
   */
  setOpacity(opacity) {
    const me = this
    if (opacity === me.options.opacity) {
      return
    }
    if (!isNaN(opacity)) {
      me.options.opacity = opacity
      me._updateOpacity()
    }
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.redraw
   * @description 重绘该图层。
   * @returns {boolean} 返回是否重绘成功。
   */
  redraw() {
    const me = this
    if (!me.renderer) {
      return false
    }
    if (me._map) {
      me.redrawThematicFeatures(me._map.getBounds())
    } else {
      me.redrawThematicFeatures()
    }
    return true
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.on
   * @description 添加专题要素事件监听。添加专题要素事件监听。
   * @param {Event} event - 监听事件。
   * @param {Function} callback - 回调函数。
   * @param {string} context - 信息。
   */
  on(event, callback, context) {
    // eslint-disable-line no-unused-vars
    if (this.renderer) {
      this.renderer.on(event, callback)
    } else {
      L.Layer.prototype.on.call(this, event, callback)
    }
    return this
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.off
   * @description 移除专题要素事件监听。
   * @param {Event} event - 监听事件。
   * @param {Function} callback - 回调函数。
   * @param {string} context -  信息。
   */
  off(event, callback, context) {
    // eslint-disable-line no-unused-vars
    const me = this
    if (me.renderer) {
      me.renderer.un(event, callback)
    } else {
      L.Layer.prototype.off.call(this, event, callback)
    }
    return this
  },
  fire(type, data, propagate) {
    // eslint-disable-line no-unused-vars
    if (this.renderer) {
      this.renderer.trigger(type, data)
    }
    L.Layer.prototype.fire.call(this, type, data, propagate)
    return this
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.addTFEvents
   * @description 将图层添加到地图上之前用户要求添加的事件监听添加到图层。
   * @private
   */
  addTFEvents() {
    const me = this
    const tfEs = me.TFEvents
    const len = tfEs.length
    for (let i = 0; i < len; i++) {
      me.renderer.on(tfEs[i][0], tfEs[i][1])
    }
  },
  /**
   * @function Zondy.ThemeLayer.ThemeLayer.prototype.getLocalXY
   * @description 地理坐标转为像素坐标。
   * @param {Array} coordinate
   */
  getLocalXY(coordinate) {
    if (!this._map) {
      return coordinate
    }
    let coor = coordinate
    if (L.Util.isArray(coordinate)) {
      coor = L.point(coordinate[0], coordinate[1])
    } else if (!(coordinate instanceof L.Point)) {
      if (coordinate instanceof Zondy.LonLat) {
        coor = L.point(coordinate.lon, coordinate.lat)
      } else {
        coor = L.point(coordinate.x, coordinate.y)
      }
    }
    const point = this._map.latLngToContainerPoint(
      this._map.options.crs.unproject(coor)
    )
    return [point.x, point.y]
  },
  _initContainer() {
    const parentContainer = this.getPane()
    const animated = this._map.options.zoomAnimation && L.Browser.any3d
    let className = this.options.name || 'themeLayer'
    className += ` leaflet-layer leaflet-zoom-${animated ? 'animated' : 'hide'}`
    this.container = L.DomUtil.create('div', className, parentContainer)
    const originProp = L.DomUtil.testProp([
      'transformOrigin',
      'WebkitTransformOrigin',
      'msTransformOrigin'
    ])
    this.container.style[originProp] = '50% 50%'
    this.container.style.position = 'absolute'
    this.container.style.zIndex = 200
  },
  _zoomAnim(e) {
    const scale = this._map.getZoomScale(e.zoom)
    const offset = this._map
      ._getCenterOffset(e.center)
      ._multiplyBy(-scale)
      .subtract(this._map._getMapPanePos())
    if (L.DomUtil.setTransform) {
      L.DomUtil.setTransform(this.container, offset, scale)
    } else {
      this.container.style[
        L.DomUtil.TRANSFORM
      ] = `${L.DomUtil.getTranslateString(offset)} scale(${scale})`
    }
  },
  _updateOpacity() {
    const me = this
    modifyDOMElement(
      me.container,
      null,
      null,
      null,
      null,
      null,
      null,
      me.options.opacity
    )
    if (me._map !== null) {
      /**
       * @event Zondy.ThemeLayer.ThemeLayer#changelayer
       * @description 图层属性改变之后触发。
       * @property {Object} layer - 图层。
       * @property {string} property - 图层属性。
       */
      me._map.fire('changelayer', {
        layer: me,
        property: 'opacity'
      })
    }
  },
  // 缩放移动重绘
  _reset() {
    const me = this
    const latLngBounds = me._map.getBounds()
    me.update(latLngBounds)
    const size = me._map.getSize()
    const mapOffset = this._map.containerPointToLayerPoint([0, 0])
    L.DomUtil.setPosition(this.container, mapOffset)
    if (parseFloat(me.container.width) !== parseFloat(size.x)) {
      me.container.width = `${size.x}px`
    }
    if (parseFloat(me.container.height) !== parseFloat(size.y)) {
      me.container.height = `${size.y}px`
    }
    me.redraw()
  },
  // 通知渲染器的尺寸变化
  _resize() {
    const me = this
    const newSize = me._map.getSize()
    me.container.style.width = `${newSize.x}px`
    me.container.style.height = `${newSize.y}px`
    me.renderer.resize()
  }
})
Zondy.ThemeLayer.ThemeLayer = ThemeLayer
export default ThemeLayer
</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>