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