UNPKG

@web-map-service/map2d-app

Version:

基于openlayer的2D地图应用

293 lines (262 loc) 8.43 kB
import { App, Plugin } from '../types' import { elements } from '@web-map-service/map2d-app' import { setElementsData, Element } from '../elements' import { util } from '../shared' function getElementExtreme(type: RankType, element: Element) { const sElement = element.getSElement() let elementExtreme; if (sElement.type === 'circle') { // 圆形 // 间距 const distance = (sElement as elements.SElement<'circle'>)['data'].radius // 是否使用当前元素的极限值替换最终极限值 if (type === 'left') { elementExtreme = (sElement as elements.SElement<'circle'>)['data'].center[0] - distance; } if (type === 'right') { elementExtreme = (sElement as elements.SElement<'circle'>)['data'].center[0] + distance; } if (type === 'top') { elementExtreme = (sElement as elements.SElement<'circle'>)['data'].center[1] + distance; } if (type === 'bottom') { elementExtreme = (sElement as elements.SElement<'circle'>)['data'].center[1] - distance; } } else { // 多边形、线段 for (const coord of sElement['data']) { // 是否使用当前元素的极限值替换最终极限值 if (type === 'left' || type === 'right') { if (util.isUnDef(elementExtreme)) { elementExtreme = coord[0]; continue } if (type === 'left') { elementExtreme = elementExtreme < coord[0] ? elementExtreme : coord[0]; continue } if (type === 'right') { elementExtreme = elementExtreme > coord[0] ? elementExtreme : coord[0]; continue } } if (type === 'top' || type === 'bottom') { if (util.isUnDef(elementExtreme)) { elementExtreme = coord[1]; continue } if (type === 'top') { elementExtreme = elementExtreme > coord[1] ? elementExtreme : coord[1]; continue } if (type === 'bottom') { elementExtreme = elementExtreme < coord[1] ? elementExtreme : coord[1]; continue } } } } return elementExtreme } function getExtreme(type: RankType, elements: Element[]) { // 找出极限值 let extreme: number | undefined = undefined for (const element of elements) { let useSElementExtreme = false const elementExtreme = getElementExtreme(type, element) // extreme 不存在直接赋值 if (util.isUnDef(extreme)) { extreme = elementExtreme continue } if (type === 'left') { useSElementExtreme = extreme > elementExtreme } if (type === 'right') { useSElementExtreme = extreme < elementExtreme } if (type === 'top') { useSElementExtreme = extreme < elementExtreme } if (type === 'bottom') { useSElementExtreme = extreme > elementExtreme } if (!useSElementExtreme) continue extreme = elementExtreme } return extreme! } function syncElements(type: RankType, app: App, extreme: number, elements: Element[]) { // 所有元素极限排列 const elementsSetDataItems: Parameters<typeof setElementsData>['0'] = [] for (const element of elements) { const sElement = element.getSElement() const elementExtreme = getElementExtreme(type, element) // 计算需要移动的大小 const distance = extreme - elementExtreme let data: Element['data'] = [] if (sElement.type === 'circle') { // 圆形 let x: number | undefined = undefined let y: number | undefined = undefined if (type === 'left' || type === 'right') { x = sElement.data.center[0] + distance y = sElement.data.center[1] } if (type === 'top' || type === 'bottom') { x = sElement.data.center[0] y = sElement.data.center[1] + distance } if (type === 'centerX') { x = extreme y = sElement.data.center[1] } if (type === 'centerY') { x = sElement.data.center[0] y = extreme } data = { radius: sElement.data.radius, center: [x!, y!] } } else { // 多边形、线段 data = [] if (type === 'left' || type === 'right') { for (const coord of sElement.data) { data.push([coord[0] + distance, coord[1]]) } } if (type === 'top' || type === 'bottom') { for (const coord of sElement.data) { data.push([coord[0], coord[1] + distance]) } } if (type === 'centerX') { const leftElementExtreme = getElementExtreme('left', element) const rightElementExtreme = getElementExtreme('right', element) const distance = (rightElementExtreme + leftElementExtreme) / 2 - extreme for (const coord of sElement.data) { data.push([coord[0] - distance, coord[1]]) } } if (type === 'centerY') { const topElementExtreme = getElementExtreme('top', element) const bottomElementExtreme = getElementExtreme('bottom', element) const distance = (topElementExtreme + bottomElementExtreme) / 2 - extreme for (const coord of sElement.data) { data.push([coord[0], coord[1] - distance]) } } } elementsSetDataItems.push({ element, data: { data } }) } setElementsData(elementsSetDataItems, app.emitter) app.emitter.emit('rank', { elements, type, extreme }) } function leftAlign(app: App, elements: Element[]) { const extreme: number = getExtreme('left', elements) syncElements('left', app, extreme, elements) } function rightAlign(app: App, elements: Element[]) { const extreme: number = getExtreme('right', elements) syncElements('right', app, extreme, elements) } function topAligin(app: App, elements: Element[]) { const extreme: number = getExtreme('top', elements) syncElements('top', app, extreme, elements) } function bottomAligin(app: App, elements: Element[]) { const extreme: number = getExtreme('bottom', elements) syncElements('bottom', app, extreme, elements) } function centerAliginX(app: App, elements: Element[]) { const leftExtreme: number = getExtreme('left', elements) const rightExtreme: number = getExtreme('right', elements) const extreme = (leftExtreme + rightExtreme) / 2 syncElements('centerX', app, extreme, elements) } function centerAliginY(app: App, elements: Element[]) { const topExtreme: number = getExtreme('top', elements) const bottomExtreme: number = getExtreme('bottom', elements) const extreme = (topExtreme + bottomExtreme) / 2 syncElements('centerY', app, extreme, elements) } type RankType = 'left' | 'right' | 'top' | 'bottom' | 'centerX' | 'centerY' function makeTool(app: App) { const select = app.tools.select; const tool = { enabled: false, enable() { if (tool.enabled) return tool.enabled = true }, use(type: RankType) { if (!tool.enabled) return const elements = select.getSelected() // 小于2个元素不进行排列 if (elements.length < 2) return if (type === 'left') { leftAlign(app, elements) return } if (type === 'right') { rightAlign(app, elements) return } if (type === 'centerX') { centerAliginX(app, elements) return } if (type === 'centerY') { centerAliginY(app, elements) return } if (type === 'top') { topAligin(app, elements) return } if (type === 'bottom') { bottomAligin(app, elements) return } }, close() { if (!tool.enabled) return tool.enabled = false } } return tool } export function createPlugin() { let app: App const plugin: Plugin = { type: 'rank', depend: ['select'], install(_app: App) { app = _app app.tools.rank = makeTool(app) return app }, } return plugin } declare module './tool' { interface Tools { rank: ReturnType<typeof makeTool> } } declare module '../types' { interface AppEmitterEvent { rank: any } }