Commit cdc77c41 authored by 郭铭瑶's avatar 郭铭瑶 🤘

文件目录调整&添加线状覆盖物

parent 6f71d48c
......@@ -5,19 +5,21 @@
<div @click="zoomOut">-</div>
<div @click="zoomTo">To</div>
<div @click="move">Move</div>
<div @click="addPoints">Add</div>
<div @click="removePoints">Remove</div>
<div @click="addPoints">Point</div>
<div @click="addLines">Line</div>
<div @click="removeLayers">Remove</div>
</div>
</div>
</template>
<script lang="ts" setup>
import icon1 from '@/assets/images/icon1.png'
import MyMap from '@/map/my-map'
import useMap from '@/map'
import MyMap from '@/my-map/my-map'
import useMap from '@/my-map'
import { nextTick, onMounted } from 'vue'
let map: MyMap
let pointsLayer: any
let linesLayer: any
onMounted(async () => {
await nextTick()
......@@ -42,7 +44,7 @@ onMounted(async () => {
map
.on('load', addControls)
.on('click', (a, b) => console.log('click', a, b))
.on('click', (a, b) => console.log(a, b))
.on('zoom', (e) => console.log('zoom: ', e))
.on('move', (e) => console.log('move: ', e))
.on('blur', (e) => console.log('blur: ', e))
......@@ -101,8 +103,20 @@ function addPoints() {
},
})
}
function removePoints() {
function addLines() {
linesLayer = map.add('line', {
data: {
path: [
[0, 0],
[121.59751247938203, 29.835174764721145],
],
text: 'test message',
},
})
}
function removeLayers() {
map.remove(pointsLayer)
map.remove(linesLayer)
}
</script>
......
import MyMap from './my-map'
import MyMap from '../my-map'
import {
CallBack,
MapConfig,
......@@ -10,19 +10,10 @@ import {
ClickCallBack,
Controls,
AIMapConfig,
Markers,
PointData,
} from './types'
declare const aimap: {
Map: any
accessToken: string
baseApiUrl: string
NavigationControl: any
CompassControl: any
ScaleControl: any
MassMarkerLayer: any
}
Layers,
LayerOption,
} from '../types'
import { toLines, toPoints } from './util'
export default class AI_Map extends MyMap {
private _clickCb: ClickCallBack | null = null
......@@ -52,7 +43,7 @@ export default class AI_Map extends MyMap {
super(instance)
this._setListeners()
this._setControls()
this._setMarkers()
this._setLayers()
}
/** 设置监听事件 */
......@@ -126,62 +117,28 @@ export default class AI_Map extends MyMap {
this._controls = Object.assign(this._controls, _controls)
}
/** 转化点状覆盖物 */
private _toPoints(options: PointData) {
const {
data,
size = 20,
icon,
labelKey,
spatialReference = 'gcj02',
labelOptions,
} = options
const [horizontal, vertical] = labelOptions?.offset || []
return {
map: this.map,
spatialReference: spatialReference,
data: data.map((item, i: number) => {
const x = item.X || item.x || item.gpsx
const y = item.Y || item.y || item.gpsy
if ((x !== 0 && !x) || (y !== 0 && !y)) {
console.error(`add point: 非法的坐标[${x}, ${y}] 存在于数据: ${item}`)
}
const z = item.Z || item.z || item.gpsz || 0
return {
...item,
id: item.id || i,
icon: item.icon ? `icon${i}` : 'icon',
spatialReference: spatialReference || item.spatialReference,
coordinates: z ? [x, y, z] : [x, y],
}
}),
images: data.map((item: any, i: number) => {
return {
id: item.icon ? `icon${i}` : 'icon',
url: item.icon || icon,
/** 设置覆盖物 */
private _setLayers() {
const _markers: Partial<Layers> = {
point: (data: LayerOption) => {
const layer = new aimap.MassMarkerLayer(toPoints(this.map, data))
// 维智的覆盖物点击事件需特别定义
layer.on('click', (e: any) => {
const arg = {
type: e.type,
center: [e.lngLat.lng, e.lngLat.lat],
event: e.originalEvent,
clientX: e.point.x,
clientY: e.point.y,
originData: e,
}
}),
style: {
'text-field': `{${labelKey}}`,
'text-color': labelOptions?.color,
// 偏移相比测绘院地图大概小了10倍,且竖直偏移相反
'text-offset': [
horizontal ? horizontal / 10 : 0,
vertical ? vertical / -10 : 0,
],
'icon-anchor': 'center',
'icon-image': ['get', 'icon'],
// size相比测绘院地图大概小了50倍
'icon-size': Array.isArray(size) ? size[0] / 50 : size / 50,
// 点击覆盖物获取自定义数据
this._clickCb && this._clickCb(arg, e?.features?.[0]?.properties)
})
return layer
},
}
}
/** 设置覆盖物方法 */
private _setMarkers() {
const _markers: Partial<Markers> = {
point: (data: PointData) => {
const layer = new aimap.MassMarkerLayer(this._toPoints(data))
line: (data: LayerOption) => {
const layer = new aimap.MassMarkerLayer(toLines(this.map, data))
// 维智的覆盖物点击事件需特别定义
layer.on('click', (e: any) => {
const arg = {
......@@ -217,6 +174,6 @@ export default class AI_Map extends MyMap {
})
}
remove(layer: any) {
layer.remove()
layer && layer.remove()
}
}
import { LayerOption, PointsData } from '../types'
/** 转化点状覆盖物 */
export function toPoints(map: unknown, options: LayerOption) {
const {
data,
size = 20,
icon,
labelKey,
spatialReference = 'gcj02',
labelOptions,
} = options
const [horizontal, vertical] = labelOptions?.offset || []
const result: any = { data: [], images: [] }
const transData = (item: PointsData, i: number) => {
const x = item.X || item.x || item.gpsx
const y = item.Y || item.y || item.gpsy
if ((x !== 0 && !x) || (y !== 0 && !y)) {
console.error(`add point: 非法的坐标[${x}, ${y}] 存在于数据: ${item}`)
}
const z = item.Z || item.z || item.gpsz || 0
result.data.push({
...item,
id: item.id || i,
icon: item.icon ? `icon${i}` : 'icon',
spatialReference: spatialReference || item.spatialReference,
coordinates: z ? [x, y, z] : [x, y],
})
result.images.push({
id: item.icon ? `icon${i}` : 'icon',
url: item.icon || icon,
})
}
if (Array.isArray(data)) {
data.forEach(transData)
} else {
transData(data, 0)
}
return {
map,
spatialReference: spatialReference,
data: result.data,
images: result.images,
style: {
'text-field': `{${labelKey}}`,
'text-color': labelOptions?.color,
// 偏移相比测绘院地图大概小了10倍,且竖直偏移相反
'text-offset': [
horizontal ? horizontal / 10 : 0,
vertical ? vertical / -10 : 0,
],
'icon-anchor': 'center',
'icon-image': ['get', 'icon'],
// size相比测绘院地图大概小了50倍
'icon-size': Array.isArray(size) ? size[0] / 50 : size / 50,
},
}
}
/** 转化线状覆盖物 */
export function toLines(map: unknown, options: LayerOption) {
const {
data,
lineWidth = 3,
color = 'blue',
labelKey,
spatialReference = 'gcj02',
labelOptions,
lineJoin = 'round',
} = options
const [horizontal, vertical] = labelOptions?.offset || []
return {
map,
spatialReference: spatialReference,
data: {
coordinates: Array.isArray(data)
? data.map(({ path }) => path?.map((e) => e))
: data.path,
...data,
},
style: {
'line-width': lineWidth,
'line-color': color,
'line-join': lineJoin,
'text-field': `{${labelKey}}`,
'text-color': labelOptions?.color,
// 偏移相比测绘院地图大概小了10倍,且竖直偏移相反
'text-offset': [
horizontal ? horizontal / 10 : 0,
vertical ? vertical / -10 : 0,
],
},
}
}
......@@ -31,3 +31,20 @@ const whichMap = {
export default function useMap<K extends keyof typeof whichMap>(key: K) {
return whichMap[key]
}
// function _injectSource(sources: any[]): Promise<unknown[]> {
// const promises = sources.map((source: string, index: number) => {
// return new Promise((resolve) => {
// const id = `_my_map_source${index}`
// if (document.getElementById(id)) return resolve(true)
// const mapSource = document.createElement('script')
// mapSource.type = 'text/javascript'
// mapSource.src = source
// mapSource.setAttribute('id', id)
// document.body.appendChild(mapSource)
// mapSource.onload = () => resolve(true)
// })
// })
// return Promise.all(promises)
// }
declare const SMap: {
Map: any
MapEvent: any
Size: any
Icon: any
Label: any
Marker: any
Polyline: any
OverlayGroup: any
Network: any
Home: any
Zoom: any
Compass: any
Fullscreen: any
LayerListControl: any
MeasureLine: any
MeasureArea: any
BasemapToggle: any
UndergroundSwitch: any
BMapGallery: any
BMapGalleryExpand: any
LngLat: any
}
declare const Plugins: {
MaskBoundary: any
}
declare const aimap: {
Map: any
accessToken: string
baseApiUrl: string
NavigationControl: any
CompassControl: any
ScaleControl: any
MassMarkerLayer: any
}
......@@ -6,15 +6,15 @@ import {
ZoomOptions,
FocusOptions,
Location,
Markers,
PointData,
Layers,
LayerOption,
} from './types'
export default abstract class MyMap {
protected map
protected _listeners: Listeners
protected _controls: Controls
protected _markers: Markers
protected _markers: Layers
constructor(instance: any) {
this.map = instance
......@@ -89,7 +89,8 @@ export default abstract class MyMap {
},
}
this._markers = {
point: () => console.error('add:此地图不存在 point 撒点!'),
point: () => console.error('add:此地图不存在 point 覆盖物!'),
line: () => console.error('add:此地图不存在 line 覆盖物!'),
}
}
......@@ -128,7 +129,7 @@ export default abstract class MyMap {
* @param type 覆盖物类型
* @param data 覆盖物数据
*/
add<K extends keyof Markers>(type: K, data: PointData) {
add<K extends keyof Layers>(type: K, data: LayerOption) {
return this._markers[type](data)
}
......
import MyMap from './my-map'
import MyMap from '../my-map'
import {
CallBack,
MapConfig,
......@@ -8,35 +8,11 @@ import {
FocusOptions,
Controls,
SMapConfig,
Markers,
PointData,
Layers,
LayerOption,
ClickCallBack,
} from './types'
declare const SMap: {
Map: any
MapEvent: any
Size: any
Icon: any
Label: any
Marker: any
OverlayGroup: any
Network: any
Home: any
Zoom: any
Compass: any
Fullscreen: any
LayerListControl: any
MeasureLine: any
MeasureArea: any
BasemapToggle: any
UndergroundSwitch: any
BMapGallery: any
BMapGalleryExpand: any
}
declare const Plugins: {
MaskBoundary: any
}
} from '../types'
import { toLines, toPoints } from './util'
export default class S_Map extends MyMap {
constructor(config: MapConfig<SMapConfig>) {
......@@ -58,7 +34,7 @@ export default class S_Map extends MyMap {
super(instance)
this._setListeners()
this._setControls()
this._setMarkers()
this._setLayers()
this.on('load', this._clearFooter)
}
......@@ -221,50 +197,17 @@ export default class S_Map extends MyMap {
this._controls = Object.assign(this._controls, _controls)
}
/** 转化点状覆盖物 */
private _toPoints(options: PointData) {
const { data, size = 20, icon, labelKey, labelOptions } = options
return data.map((item) => {
const iconSize = Array.isArray(size)
? new SMap.Size(...size)
: new SMap.Size(size, size)
const x = item.X || item.x || item.gpsx
const y = item.Y || item.y || item.gpsy
if ((x !== 0 && !x) || (y !== 0 && !y)) {
console.error(`add point: 非法的坐标[${x}, ${y}] 存在于数据: ${item}`)
}
const z = item.Z || item.z || item.gpsz || 0
const result: any = {
icon: {
size: iconSize,
image: item.icon || icon,
/** 设置覆盖物 */
private _setLayers() {
const _markers: Partial<Layers> = {
point: (data: LayerOption) => {
const layer = new SMap.OverlayGroup(toPoints(data), {})
this.map.add(layer)
return layer
},
attributes: { ...item },
position: z ? [x, y, z] : [x, y],
}
if (labelKey) {
result.label = new SMap.Label({
text: item[labelKey] + '',
size: labelOptions?.size,
color: labelOptions?.color,
xoffset: labelOptions?.offset?.[0],
yoffset: labelOptions?.offset?.[1],
zoffset: labelOptions?.offset?.[2],
verticalAlignment: 'middle',
horizontalAlignment: 'center',
})
}
return new SMap.Marker(result)
})
}
/** 设置覆盖物方法 */
private _setMarkers() {
const _markers: Partial<Markers> = {
point: (data: PointData) => {
const layer = new SMap.OverlayGroup(this._toPoints(data), {})
this.instance.add(layer)
line: (data: LayerOption) => {
const layer = new SMap.OverlayGroup(toLines(data), {})
this.map.add(layer)
return layer
},
}
......@@ -285,6 +228,6 @@ export default class S_Map extends MyMap {
this.map.setZoomAndCenter(level, location)
}
remove(layer: unknown) {
this.map.remove(layer)
layer && this.map.remove(layer)
}
}
import { LayerOption, PointsData } from '../types'
/** 转化点状覆盖物 */
export function toPoints(options: LayerOption) {
const { data, size = 20, icon, labelKey, labelOptions } = options
const transData = (item: PointsData) => {
const iconSize = Array.isArray(size)
? new SMap.Size(...size)
: new SMap.Size(size, size)
const x = item.X || item.x || item.gpsx
const y = item.Y || item.y || item.gpsy
if ((x !== 0 && !x) || (y !== 0 && !y)) {
console.error(`add point: 非法的坐标[${x}, ${y}] 存在于数据: ${item}`)
}
const z = item.Z || item.z || item.gpsz || 0
const result: any = {
icon: {
size: iconSize,
image: item.icon || icon,
},
attributes: { ...item },
position: z ? [x, y, z] : [x, y],
}
if (labelKey) {
result.label = new SMap.Label({
text: item[labelKey] + '',
size: labelOptions?.size,
color: labelOptions?.color,
xoffset: labelOptions?.offset?.[0],
yoffset: labelOptions?.offset?.[1],
zoffset: labelOptions?.offset?.[2],
verticalAlignment: 'middle',
horizontalAlignment: 'center',
})
}
return new SMap.Marker(result)
}
if (Array.isArray(data)) {
return data.map(transData)
} else {
return [transData(data)]
}
}
/** 转化线状覆盖物 */
export function toLines(options: LayerOption) {
const {
data,
color = 'blue',
labelKey,
labelOptions,
lineCap = 'square',
lineStyle = 'solid',
lineJoin = 'round',
lineWidth = 1,
} = options
const transData = (item: PointsData) => {
const result: any = {
path: item.path?.map(([x, y]) => new SMap.LngLat(x, y)),
attributes: { ...item },
cap: lineCap,
strokeColor: color,
style: lineStyle,
lineJoin: lineJoin,
lineWidth, // 测绘院地图貌似没法设置线段粗细
}
if (labelKey) {
result.label = new SMap.Label({
text: item[labelKey] + '',
size: labelOptions?.size,
color: labelOptions?.color,
xoffset: labelOptions?.offset?.[0],
yoffset: labelOptions?.offset?.[1],
verticalAlignment: 'middle',
horizontalAlignment: 'center',
})
}
return new SMap.Polyline(result)
}
if (Array.isArray(data)) {
return data.map(transData)
} else {
return [transData(data)]
}
}
......@@ -112,6 +112,10 @@ export interface Listeners {
}
type Position = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
/**
* 控制器选项
*/
export interface ControlOptions {
show?: boolean
/** 控件位置 */
......@@ -121,6 +125,10 @@ export interface ControlOptions {
/** ScaleControl控件的距离单位 */
unit?: 'imperial' | 'metric' | 'nautical'
}
/**
* 控制器列表
*/
export interface Controls {
home: (options?: ControlOptions) => unknown
compass: (options?: ControlOptions) => unknown
......@@ -135,6 +143,8 @@ export interface Controls {
bMapGallery: (options?: ControlOptions) => unknown
bMapGalleryexpand: (options?: ControlOptions) => unknown
}
export interface ZoomOptions {
/** 如果 false ,则没有动画效果(默认true) */
animate?: boolean
......@@ -163,15 +173,16 @@ export interface FocusOptions {
maxDuration?: number
}
export interface Markers {
point: (data: PointData) => unknown
}
/**
* 点状覆盖物数据
* 覆盖物列表
*/
export interface PointData {
data: {
export interface Layers {
point: (data: LayerOption) => unknown
line: (data: LayerOption) => unknown
}
/** 覆盖物点位数据 */
export interface PointsData {
id?: string
x?: number
y?: number
......@@ -184,8 +195,15 @@ export interface PointData {
gpsz?: number
icon?: string
spatialReference?: LocationType
path?: [number, number][]
[key: string]: any
}[]
}
/**
* 覆盖物选项
*/
export interface LayerOption {
data: PointsData | PointsData[]
size?: number | [number, number]
icon?: string
spatialReference?: LocationType
......@@ -196,4 +214,9 @@ export interface PointData {
offset?: [number, number] | [number, number, number]
color?: string
}
color?: string
lineCap?: string
lineStyle?: string
lineJoin?: 'bevel' | 'round' | 'miter'
lineWidth?: number
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment