类名 leaflet/util/ConvertSymbolUtil.js
import * as L from '@mapgis/leaflet'
import {
  defaultValue,
  defined,
  SymbolType,
  Color,
  createSimpleFillSymbolCanvas
} from '@mapgis/webclient-common'
import LeafletPlugin from './LeafletPlugin'

function convertSLS(symbol, style) {
  if (!symbol) return style
  style['stroke'] = true
  style['color'] = LeafletPlugin.convertColorToRgb(
    defaultValue(symbol.color, new Color())
  )
  style['opacity'] = Color.fromColor(
    defaultValue(symbol.color, new Color())
  ).alpha
  style['weight'] = defaultValue(symbol.width, 3)
  style['lineJoin'] = defaultValue(symbol.join, 'round')
  style['lineCap'] = defaultValue(symbol.cap, 'round')
  style['dashArray'] = LeafletPlugin.convertLineDash(
    symbol.style,
    symbol.cap === 'butt'
  )
  style['marker'] = symbol.marker
}

function convertSFS(symbol, style) {
  if (!symbol) return style
  if (symbol.style !== 'solid') {
    style['fill'] = `url(${createSimpleFillSymbolCanvas(symbol, {
      lineWidth: 1
    }).toDataURL()})`
  } else {
    style['fill'] = true
  }
  style['fillColor'] = LeafletPlugin.convertColorToRgb(
    defaultValue(symbol.color, new Color())
  )
  style['fillOpacity'] = Color.fromColor(
    defaultValue(symbol.color, new Color())
  ).alpha
  const outline = symbol.outline
  const outlineStyle = {}
  convertSLS(outline, outlineStyle)
  for (const key in outlineStyle) {
    style[key] = outlineStyle[key]
  }
}

function convertSMS(symbol, style) {
  if (defined(symbol.size)) {
    style.radius = defaultValue(parseFloat(symbol.size) / 2, 10)
  }
  style.xoffset = symbol.xoffset
  style.yoffset = symbol.yoffset
  style.rotation = symbol.angle
  style.shape = symbol.style
  style.path = symbol.path
  style.fill = true
  style.fillColor = LeafletPlugin.convertColorToRgb(
    defaultValue(symbol.color, new Color())
  )
  style.fillOpacity = Color.fromColor(
    defaultValue(symbol.color, new Color())
  ).alpha
  const outline = symbol.outline
  const outlineStyle = {}
  convertSLS(outline, outlineStyle)
  for (const key in outlineStyle) {
    style[key] = outlineStyle[key]
  }
}

function convertPMS(symbol, style) {
  /**
     * var myIcon = L.icon({
      iconUrl: 'my-icon.png',
      iconSize: [38, 95],
      iconAnchor: [22, 94],
      popupAnchor: [-3, -76],
      shadowUrl: 'my-icon-shadow.png',
      shadowSize: [68, 95],
      shadowAnchor: [22, 94],
      rotationAngle:0
  });
   */
  const markerOptions = {}
  const size = [10, 10]
  if (defined(symbol.width)) {
    size[0] = parseFloat(symbol.width)
  }
  if (defined(symbol.height)) {
    size[1] = parseFloat(symbol.height)
  }
  markerOptions.iconSize = size

  if (defined(symbol.url)) {
    markerOptions.iconUrl = symbol.url
  }
  // 图片和几何点中心统一
  const anchor = [size[0] / 2, size[1] / 2]
  if (defined(symbol.xoffset)) {
    anchor[0] = symbol.xoffset + anchor[0]
  }
  if (defined(symbol.yoffset)) {
    anchor[1] = symbol.yoffset + anchor[1]
  }
  markerOptions.iconAnchor = anchor

  const icon = L.icon(markerOptions)
  style.icon = icon
  style.rotationAngle = symbol.angle
}

function convertPFS(symbol, style) {
  if (!symbol) return style
  const { width, height, xscale, yscale, xoffset, yoffset, url } = symbol
  style['fill'] = `url(${url})`
  // 设置填充细则
  style.fillDetail = {
    width,
    height,
    xscale,
    yscale,
    xoffset,
    yoffset
  }
  const outline = symbol.outline
  const outlineStyle = {}
  convertSLS(outline, outlineStyle)
  for (const key in outlineStyle) {
    style[key] = outlineStyle[key]
  }
}

function convertTS(symbol, style) {
  // 计算文本长度
  const calcWidth = LeafletPlugin.getTextWidth(
    symbol.text,
    `${symbol.font.weight} ${symbol.font.size}px ${symbol.font.family}`
  )
  // 比较行宽和文字宽
  let width = calcWidth < symbol.lineWidth ? calcWidth : symbol.lineWidth
  let letterSpacing = 'normal'
  // 压缩文字至行宽
  if (symbol.kerning) {
    const text = symbol.text || ''
    const charLength = Math.max(0, text.length - 1)
    const letterSpacingNum = parseInt(
      (symbol.lineWidth - calcWidth) / charLength
    )
    letterSpacing = `${letterSpacingNum}px`
    width = symbol.lineWidth
  }
  // 文字高度
  const height = symbol.font.size

  // 设置原点
  let aliginX = 0
  let aliginY = 0

  switch (symbol.horizontalAlignment) {
    case 'left': {
      aliginX = 0
      break
    }
    case 'right': {
      aliginX = width
      break
    }
    case 'center': {
      aliginX = width / 2
      break
    }
    default: {
      aliginX = 0
    }
  }
  switch (symbol.verticalAlignment) {
    case 'baseline': {
      // 因处理性能考虑,不解析文字字模基线,处理方式和middle一致
      aliginY = height / 2
      break
    }
    case 'top': {
      aliginY = 0
      break
    }
    case 'middle': {
      aliginY = height / 2
      break
    }
    case 'bottom': {
      aliginY = height
      break
    }
    default: {
      aliginY = 0
    }
  }
  const iconAnchor = [symbol.xoffset + aliginX, symbol.yoffset + aliginY]
  const markerOptions = {
    glyph: symbol.text,
    iconUrl: null,
    iconSize: [width, height],
    font: symbol.font,
    lineHeight: symbol.lineHeight,
    iconAnchor,
    horizontalAlignment: symbol.horizontalAlignment,
    verticalAlignment: symbol.verticalAlignment,
    glyphColor: LeafletPlugin.convertColorToRgb(
      defaultValue(symbol.color, new Color())
    ),
    haloSize: symbol.haloSize,
    haloColor: symbol.haloColor.toCssRGBAString(),
    angle: symbol.angle,
    rotated: symbol.rotated,
    backgroundColor: symbol.backgroundColor
      ? symbol.backgroundColor.toCssRGBAString()
      : undefined,
    borderLineColor: symbol.borderLineColor
      ? symbol.borderLineColor.toCssRGBAString()
      : undefined,
    borderLineSize: symbol.borderLineSize,
    lineWidth: symbol.lineWidth,
    kerning: symbol.kerning,
    letterSpacing
  }
  const icon = L.icon.glyph(markerOptions)
  style.icon = icon
}

class ConvertSymbolUtil {
  /**
   * @description 转换符号为要素样式
   * @public
   * @param {Symbol} symbol
   * @return {Object} 样式结构,参考默认样式
   */
  static convertSymboltoLeafletStyle(symbol) {
    const style = {}
    if (!symbol) return style
    switch (symbol.type) {
      case SymbolType.simpleMarker: {
        convertSMS(symbol, style)
        break
      }
      case SymbolType.pictureMarker: {
        convertPMS(symbol, style)
        break
      }
      case SymbolType.simpleLine: {
        convertSLS(symbol, style)
        break
      }
      case SymbolType.simpleFill: {
        convertSFS(symbol, style)
        break
      }
      case SymbolType.pictureFill: {
        convertPFS(symbol, style)
        break
      }
      case SymbolType.text: {
        convertTS(symbol, style)
        break
      }
      default: {
        convertSFS(symbol, style)
        break
      }
    }
    return style
  }
}
export default ConvertSymbolUtil
构造函数
成员变量
方法
事件