@web-map-service/map2d-app
Version:
基于openlayer的2D地图应用
185 lines (168 loc) • 5.02 kB
text/typescript
import { App } from '../types'
import type { Element, Layer, ElementOptions, CreateElementOption } from './types'
import { Layer as SLayer, Element as SElement, Style, ElementData, getElementData, ElementType as SElementType} from '@web-map-service/map2d'
import {ElementEmitter} from './element'
let layerId = 0
let elementId = 0
interface LayerOptions {
type: string
name?: string
createElement(app: App, sLayer: SLayer, options: CreateElementOption): Element
sElementType: SElementType[]
}
export function createLayerCommon(app: App, layerOptions: LayerOptions) {
layerId++
const { container: { layerManager } } = app.map
const sLayer = layerManager.create({})
const elements: Element[] = []
const layer: Layer = {
id: layerId,
name: layerOptions.name,
type: layerOptions.type,
sElementType: layerOptions.sElementType,
create(options) {
const element = layerOptions.createElement(app, sLayer, options)
return element
},
add(element: Element) {
const matcher = elements.findIndex((item) => item.id === element.id)
if (matcher !== -1) return
sLayer.add(element.getSElement())
elements.push(element)
},
remove(element: Element) {
const matcher = elements.findIndex((item) => item.id === element.id)
if (matcher === -1) return
sLayer.remove(element.getSElement())
elements.splice(matcher, 1)
},
getElements() {
return elements
},
getElementById(id: number) {
const element = elements.find((item) => item.id === id)
return element
}
}
return layer
}
export function createElementCommon(app: App, sLayer: SLayer, options: ElementOptions) {
elementId++
const sElement: SElement<SElementType> = sLayer.create({
type: options.sElementType!,
data: options.data,
rotate: options.rotate,
style: options.style
}, false)
const element: Element = {
id: options.id ?? elementId,
type: options.type,
name: options.name,
get props() {
return sElement.props
},
setProps(props: Record<string, unknown>) {
return sElement.setProps(props)
},
setName(name: string) {
sElement.setName(name)
},
get rotate() {
return sElement.rotate
},
setRotate(rotate: number) {
return sElement.setRotate(rotate)
},
getSElement() {
return sElement
},
get style() {
return sElement.style
},
setStyle(style: Style) {
sElement.setStyle(style)
},
get data() {
return sElement['data']
},
setData(data: ElementData) {
sElement.setData(data)
}
}
return element
}
/**
通过app和服务元素来找到应用元素, 通过打标属性appLayerType、appElementId找到Element
*/
export function getElementBySElement(app: App, sElement: SElement) {
const layerType = sElement.props.appLayerType
const elementId = sElement.props.appElementId
const layer = app.element.getLayerByType(layerType as string)
if (!layer) return
const element = layer.getElementById(elementId as number)
if (!element) return
return element
}
/**
* SElement更新data通知同步一下element数据主要是为了触发一下update反射
*/
export function syncElementsDataEmit(app: App, sElements: SElement[]) {
const elements: Element[] = []
const elementSetDataItems: ElementSetDataItem[] = []
for (const sElement of sElements) {
const olFeature = sElement.getOlFeature()
const olGeometry = olFeature.getGeometry()
if (!olGeometry) continue
const data = getElementData(olGeometry)
const element = getElementBySElement(app, sElement)
if(element && data) {
elements.push(element)
elementSetDataItems.push({
element,
data: {
data
}
})
}
}
setElementsData(elementSetDataItems, app.emitter)
return elements
}
export interface ElementSetDataItem {
element: Element
data: Partial<{
data: Element['data']
style: Element['style']
rotate: Element['rotate']
name: Element['name']
}>
}
function setElementData(elementSetDataItem: ElementSetDataItem) {
const element = elementSetDataItem.element
const data = elementSetDataItem.data
if (data.data) {
element.setData(data.data)
}
if (data.name) {
element.setName(data.name)
}
if (data.rotate) {
element.setRotate(data.rotate)
}
if (data.style) {
element.setStyle(data.style)
}
}
/**
* 同步数据入口
* @param data
* @param emitter
*/
export function setElementsData(data: ElementSetDataItem[], emitter: App['emitter'], useSync=true) {
emitter.emit(ElementEmitter.update, data)
// 不进行数据同步,仅抛出回调事件
if (!useSync) return
for(const item of data) {
setElementData(item)
}
}