类名 leaflet/document/theme/RandomThemeLayer.js
import { Zondy, Extent } from '@mapgis/webclient-common'
import * as L from '@mapgis/leaflet'
// eslint-disable-next-line import/no-extraneous-dependencies
import { copyAttributesWithClip } from '@mapgis/webclient-graphic-render'
import GeoFeatureThemeLayer from './GeoFeatureThemeLayer'
import ThemeLayer from './ThemeLayer'

/**
 * @class Zondy.ThemeLayer.RandomThemeLayer
 * @classdesc 随机专题图。
 * @description 随机专题图对数据(<{@link Zondy.Feature.Vector}>)属性字段(attributes)的属性值进行分段,使用不同的颜色或符号(线型、填充)渲染不同范围段的属性值。
 * 随机专题图一般用来反映连续分布现象的数量或程度特征,如降水量的分布,土壤侵蚀强度的分布等。
 * @extends Zondy.ThemeLayer.GeoFeatureThemeLayer
 * @param {string} name - 图层名
 * @param {Object} options - 图层参数。
 * @param {string} [options.id] - 专题图层 ID。默认使用 CommonUtil.createUniqueID("themeLayer_") 创建专题图层 ID。
 * @param {number} [options.opacity=1] - 图层透明度。
 * @param {number} [options.nodesClipPixel=2] - 节点抽稀像素距离。
 * @param {boolean} [options.isHoverAble=false] - 图形是否在 hover 时高亮。
 * @param {boolean} [options.isMultiHover=false] - 是否多图形同时高亮,用于高亮同一个数据对应的所有图形(如:多面)。
 * @param {boolean} [options.isClickAble=true] - 图形是否可点击。
 * @param {boolean} [options.isAllowFeatureStyle=false] - 是否允许 feature 样式(style) 中的有效属性应用到专题图层。禁止对专题要素使用数据(feature)的 style。此属性可强制将数据 feature 的 style 中有效属性应用到专题要素上,且拥有比图层 style 和 styleGroups 更高的优先级,使专题要素的样式脱离专题图层的控制。可以通过此方式实现对特殊数据(feature) 对应专题要素赋予独立 style。
 */
const RandomThemeLayer = GeoFeatureThemeLayer.extend({
  /**
   * @function Zondy.ThemeLayer.RandomThemeLayer.prototype.initialize
   * @description 初始化。
   * @param {string} name - 专题图名。
   * @param {Object} options - 需要设置的参数对象。
   */
  initialize(name, options) {
    GeoFeatureThemeLayer.prototype.initialize.call(this, name, options)
    // {Array<Zondy.ThemeLayer.ThemeStyle>} 图层中专题要素的样式
    this.style = []
    // {String} 用于指定专题要素样式的属性字段名称。
    // 此属性字段是要用户数据(feature) attributes 中包含的字段,且字段对应的值的类型必须是数值型。使用标签分组显示还需要设置 styleGroups 属性。
    this.keepStyle = true
  },

  /**
   * @function Zondy.ThemeLayer.RandomThemeLayer.prototype.getColor
   * @description 获取随机颜色
   * @return {Array} color
   */
  getColor() {
    const colorValue = '0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f'
    const colorArray = colorValue.split(',')
    let color = '#' // 定义一个存放十六进制颜色值的字符串变量,先将#存放进去
    for (let i = 0; i < 6; i++) {
      color += colorArray[Math.floor(Math.random() * 16)]
    }
    return color
  },

  /**
   * @function Zondy.ThemeLayer.RandomThemeLayer.prototype.getStyleByData
   * @return {Array<Zondy.ThemeLayer.ThemeStyle>} 专题要素的 Style
   */
  getStyleByData() {
    const me = this
    const style = copyAttributesWithClip({}, me.style)
    style.fillColor = me.getColor()
    return style
  },

  /**
   * @function Zondy.ThemeLayer.RandomThemeLayer.prototype.onAdd
   * @description 添加专题图
   * @param map - {L.map} 要添加的地图
   */
  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.zoomstartHandler = function (e) {
      me.keepStyle = false
      // alert('start');
    }
    map.on('zoomstart ', me.zoomstartHandler)
    me.zoomendHandler = function (e) {
      me.keepStyle = true
      // alert('end');
    }
    map.on('zoomend', me.zoomendHandler)

    me.update()
  },

  /**
   * @function Zondy.ThemeLayer.RandomThemeLayer.prototype.redrawThematicFeatures
   * @description 重绘专题要素
   * @param bounds - {L.Bounds} 地图范围
   */
  redrawThematicFeatures(bounds) {
    const me = this
    // 获取高亮专题要素对应的用户 id
    const hoverone = me.renderer.getHoverOne()
    let hoverFid = null
    if (hoverone && hoverone.refDataID) {
      hoverFid = hoverone.refDataID
    }
    const features = me.features
    if (bounds && bounds instanceof L.LatLngBounds) {
      const crs = this._map.options.crs
      bounds = L.bounds(
        crs.project(bounds.getSouthWest()),
        crs.project(bounds.getNorthEast())
      )
      bounds = new Extent({
        xmin: bounds.min.x,
        ymin: bounds.min.y,
        xmax: bounds.max.x,
        ymax: bounds.max.y
      })
    }
    // 清除当前所有可视元素
    me.renderer.clearAll()

    const cache = me.cache
    const cacheFields = me.cacheFields
    const cmZoom = me._map.getZoom()

    const maxCC = me.maxCacheCount

    for (let i = 0, len = features.length; i < len; i++) {
      const feature = features[i]

      if (!feature || !feature.geometry) {
        continue
      }
      // 要素范围判断
      const feaBounds = feature.geometry.extent
      // 剔除当前视图(地理)范围以外的数据
      if (bounds && !bounds.intersects(feaBounds)) {
        continue
      }

      // 缓存字段
      const fields = `${feature.FID}_zoom_${cmZoom.toString()}`
      if (cache[fields] && me.keepStyle) {
        cache[fields].updateAndAddShapes()
        continue
      }

      const thematicFeature = me.createThematicFeature(features[i])
      // 检查 thematicFeature 是否有可视化图形
      if (thematicFeature.getShapesCount() < 1) {
        continue
      }
      // 加入缓存
      cache[fields] = thematicFeature
      cacheFields.push(fields)
      // 缓存数量限制
      if (cacheFields.length > maxCC) {
        const fieldsTemp = cacheFields[0]
        cacheFields.splice(0, 1)
        delete cache[fieldsTemp]
      }
      // console.log("total: %d ,current:%d", features.length,i);
    }

    me.renderer.render()

    // 地图漫游后,重新高亮图形
    if (hoverFid && me.options.isHoverAble && me.options.isMultiHover) {
      const hShapes = this.getShapesByFeatureID(hoverFid)
      this.renderer.updateHoverShapes(hShapes)
    }
  },

  /**
   * @function Zondy.ThemeLayer.RandomThemeLayer.prototype.redraw
   * @description 重绘专题图
   */
  redraw() {
    if (!this.keepStyle) {
      this.clearCache()
    }
    return ThemeLayer.prototype.redraw.apply(this, arguments)
  }
})

Zondy.ThemeLayer.RandomThemeLayer = RandomThemeLayer
export default RandomThemeLayer
构造函数
成员变量
方法
事件