类名 leaflet/util/LeafletPlugin.js
import {
  Log,
  Projection,
  SpatialReference,
  Point,
  GeometryType,
  Color
} from '@mapgis/webclient-common'
import * as L from '@mapgis/leaflet'

class LeafletPlugin {
  /**
   * @description 颜色转换
   * @private
   * @param {Color|String} color
   * @return {String}
   */
  static convertColorToRgb(color) {
    if (color instanceof Color) {
      return color.toCssRGBAString()
    }
    return color
  }

  /**
   * @description: 转换为经纬度坐标系下几何
   * @param {*} geometry
   * @return {*}
   */
  static convertLngLatGeometry(geometry) {
    if (!geometry || !geometry.spatialReference) return geometry
    if (String(geometry.spatialReference.wkid) !== '4326') {
      return Projection.project(geometry, new SpatialReference('EPSG:4326'))
    }
    return geometry
  }

  /**
   * @description: 转换裁剪区域
   * @param {Polygon|Extent|Circle|null} clippingArea
   * @return {Number[][][]|null}
   */
  static convertClippingArea(clippingArea) {
    if (!clippingArea) return clippingArea
    let clippingAreaCoords = null
    switch (clippingArea.type) {
      case GeometryType.polygon:
        clippingAreaCoords =
          LeafletPlugin.convertLngLatGeometry(clippingArea).coordinates
        break
      case GeometryType.circle: {
        const circle = LeafletPlugin.convertLngLatGeometry(clippingArea)
        clippingAreaCoords = circle.toPolygon().coordinates
        break
      }
      case GeometryType.extent: {
        const extent = LeafletPlugin.convertLngLatGeometry(clippingArea)
        const { xmin, xmax, ymin, ymax } = extent
        clippingAreaCoords = [
          [
            [xmin, ymax],
            [xmax, ymax],
            [xmax, ymin],
            [xmin, ymin],
            [xmin, ymax]
          ]
        ]
        break
      }
      default:
        break
    }

    return clippingAreaCoords
  }

  /**
   * @description 转换线样式
   * @private
   * @param {String} lineStyle
   * @param {String} isButt
   * @return {String}
   */
  static convertLineDash(lineStyle, isButt) {
    switch (lineStyle) {
      case 'dash':
        return isButt ? [4, 3] : [3, 4]
      case 'dash-dot':
        return isButt ? [4, 3, 1, 3] : [3, 4, 0, 4]
      case 'dot':
        return isButt ? [1, 3] : [0, 4]
      case 'long-dash':
        return isButt ? [8, 3] : [7, 4]
      case 'long-dash-dot':
        return isButt ? [8, 3, 1, 3] : [7, 4, 0, 4]
      case 'long-dash-dot-dot':
        return isButt ? [8, 3, 1, 3, 1, 3] : [7, 4, 0, 4, 0, 4]
      case 'short-dash':
        return isButt ? [4, 1] : [3, 2]
      case 'short-dash-dot':
        return isButt ? [4, 1, 1, 1] : [3, 2, 0, 2]
      case 'short-dash-dot-dot':
        return isButt ? [4, 1, 1, 1, 1, 1] : [3, 2, 0, 2, 0, 2]
      case 'short-dot':
        return isButt ? [1, 1] : [0, 2]
      case 'solid':
      case 'none':
        return undefined
      default:
        return undefined
    }
  }

  static calcLineMarkerDetail(coords) {
    if (!coords || (Array.isArray(coords) && coords.length <= 1)) {
      Log.error('计算线样式首尾marker错误,传入几何数组不合法')
    }
    // 此处计算角度可能在不同坐标系下会发生偏移
    const p1 = coords[0]
    const p2 = coords[1]
    const p3 = coords[coords.length - 2]
    const p4 = coords[coords.length - 1]

    const angle1 =
      360 -
      ((((Math.atan2(p2[1] - p1[1], p2[0] - p1[0]) * 180) / Math.PI + 180) %
        360) -
        90)
    const angle2 =
      360 -
      ((((Math.atan2(p3[1] - p4[1], p3[0] - p4[0]) * 180) / Math.PI + 180) %
        360) -
        90)

    const _latlng1 = Projection.project(
      new Point({
        coordinates: p1
      }),
      new SpatialReference('EPSG:4326')
    ).coordinates
    const _latlng2 = Projection.project(
      new Point({
        coordinates: p4
      }),
      new SpatialReference('EPSG:4326')
    ).coordinates

    const latlng1 = L.latLng(_latlng1[1], _latlng1[0])
    const latlng2 = L.latLng(_latlng2[1], _latlng2[0])

    return {
      latlng1,
      latlng2,
      angle1,
      angle2
    }
  }

  /**
   * 使用canvas画布。测量文本以计算并返回给定字体的给定文本的宽度(以像素为单位)。
   * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
   * 要呈现的文本
   * @private
   * @param {String} text The text to be rendered.
   * 用于呈现文本的css字体描述符
   * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
   * @param {Object} styleObject 样式对象
   */
  static getTextWidth(text, font) {
    // 重用canvas对象以获得更好的性能
    // re-use canvas object for better performance
    const canvas =
      LeafletPlugin.getTextWidth.canvas ||
      (LeafletPlugin.getTextWidth.canvas = document.createElement('canvas'))
    const context = canvas.getContext('2d')
    context.font = font
    const metrics = context.measureText(text)
    return metrics.width
  }

  /**
   * @description: 获取几何区域中心
   * @param {*} geometry
   * @return {*}
   */
  static getAreaCenter(geometry) {
    let p
    switch (geometry.type) {
      case GeometryType.point: {
        p = geometry.clone()
        break
      }
      case GeometryType.multiPoint:
      case GeometryType.lineString:
      case GeometryType.multiLineString:
      case GeometryType.multiPolygon: {
        p = geometry.extent.center
        break
      }
      case GeometryType.polygon: {
        p = geometry.centroid
        break
      }
      case GeometryType.extent: {
        p = geometry.center
        break
      }
      case GeometryType.circle: {
        p = geometry.center
        break
      }
      default: {
        p = geometry.extent.center
      }
    }
    const _latlng = LeafletPlugin.convertLngLatGeometry(p).coordinates
    const latlng = L.latLng(_latlng[1], _latlng[0])
    return latlng
  }

  /**
   * @description: 设置innerLayer透明度
   * @param {*} innerLayer
   * @param {*} opacity
   * @param {*} visible
   * @return {*}
   */
  static setVisibleOpacity(innerLayer, opacity, visible) {
    if (!innerLayer) return
    // 设置图层透明度
    innerLayer.layerOpacity = opacity
    // 设置图层显示或隐藏
    innerLayer.layerVisible = visible
    LeafletPlugin.setGraphicVisibleOpacity(innerLayer, opacity, visible)
  }

  /**
   * @description: 设置几何图元透明度
   * @param {*} graphic
   * @param {*} opacity
   * @param {*} visible
   * @return {*}
   */
  static setGraphicVisibleOpacity(graphic, opacity, visible) {
    if (graphic.setStyle) {
      graphic.setStyle({
        opacity: visible ? opacity : 0,
        fillOpacity: visible ? opacity : 0
      })
    }
    if (graphic instanceof L.Marker) {
      graphic.setOpacity(visible ? opacity : 0)
    }
    if (graphic.eachLayer) {
      graphic.eachLayer(function (subGraphic) {
        LeafletPlugin.setGraphicVisibleOpacity(subGraphic, opacity, visible)
      })
    }
    // 解决聚类专题图聚合点无法设置透明度问题
    if (graphic._nonPointGroup) {
      LeafletPlugin.setGraphicVisibleOpacity(
        graphic._nonPointGroup,
        opacity,
        visible
      )
    }
    if (graphic._featureGroup) {
      LeafletPlugin.setGraphicVisibleOpacity(
        graphic._featureGroup,
        opacity,
        visible
      )
    }
  }
}

export default LeafletPlugin
构造函数
成员变量
方法
事件