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