Commit 6f71d48c authored by 郭铭瑶's avatar 郭铭瑶 🤘

撒点方法

parent 1e290eb3
......@@ -5,36 +5,41 @@
<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>
</div>
</template>
<script lang="ts" setup>
import useMap from '@/map'
import icon1 from '@/assets/images/icon1.png'
import MyMap from '@/map/my-map'
import useMap from '@/map'
import { nextTick, onMounted } from 'vue'
let map: MyMap
let pointsLayer: any
onMounted(async () => {
await nextTick()
map = useMap('SMap').with({
el: 'container',
center: [0, 0],
zoom: 5,
style: 'smap://styles/dark',
appKey: 'ACF69EDK17LON63GHPF081',
netType: 'internet',
})
// map = useMap('AIMap').with({
// map = useMap('SMap').with({
// el: 'container',
// center: [121.612846, 31.205494],
// zoom: 13,
// style: 'aimap://styles/aimap/darkblue-v4',
// appKey: 'gt8XidVe5upHf7cirkJwwXTCWj20zfu3',
// baseApiUrl: 'https://location-dev.newayz.com',
// center: [0, 0],
// zoom: 5,
// style: 'smap://styles/dark',
// appKey: 'ACF69EDK17LON63GHPF081',
// netType: 'internet',
// })
map = useMap('AIMap').with({
el: 'container',
center: [121.612846, 31.205494],
zoom: 13,
style: 'aimap://styles/aimap/darkblue-v4',
appKey: 'gt8XidVe5upHf7cirkJwwXTCWj20zfu3',
baseApiUrl: 'https://location-dev.newayz.com',
})
map
.on('load', addControls)
.on('click', (a, b) => console.log('click', a, b))
......@@ -75,6 +80,30 @@ function zoomTo() {
function move() {
map.focus([121.59751247938203, 29.835174764721145], { zoom: 16 })
}
function addPoints() {
pointsLayer = map.add('point', {
data: [
{
x: 121.59751247938203,
y: 29.835174764721145,
text: 'test message',
title: 'icon',
},
],
size: 20,
icon: icon1,
labelKey: 'title',
labelOptions: {
size: 20,
offset: [0, 20],
color: '#fff',
},
})
}
function removePoints() {
map.remove(pointsLayer)
}
</script>
<style scoped>
......@@ -93,7 +122,7 @@ function move() {
margin: 10px;
background: #fff;
color: #000;
min-width: 20px;
min-width: 40px;
text-align: center;
cursor: pointer;
}
......
......@@ -10,6 +10,8 @@ import {
ClickCallBack,
Controls,
AIMapConfig,
Markers,
PointData,
} from './types'
declare const aimap: {
......@@ -19,9 +21,11 @@ declare const aimap: {
NavigationControl: any
CompassControl: any
ScaleControl: any
MassMarkerLayer: any
}
export default class AI_Map extends MyMap {
private _clickCb: ClickCallBack | null = null
constructor(config: MapConfig<AIMapConfig>) {
if (!config.appKey) {
throw new Error('AIMap需要设置appKey参数!')
......@@ -48,8 +52,10 @@ export default class AI_Map extends MyMap {
super(instance)
this._setListeners()
this._setControls()
this._setMarkers()
}
/** 设置监听事件 */
private _setListeners() {
const _listeners: Partial<Listeners> = {
load: (cb: CallBack) => {
......@@ -74,6 +80,7 @@ export default class AI_Map extends MyMap {
this.map.on('resize', cb)
},
click: (cb: ClickCallBack) => {
this._clickCb = cb
this.map.on('click', (e: any) => {
const arg = {
type: e.type,
......@@ -90,6 +97,7 @@ export default class AI_Map extends MyMap {
this._listeners = Object.assign(this._listeners, _listeners)
}
/** 设置控制器 */
private _setControls() {
const _controls: Partial<Controls> = {
compass: (options?: ControlOptions) => {
......@@ -118,6 +126,81 @@ 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,
}
}),
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,
},
}
}
/** 设置覆盖物方法 */
private _setMarkers() {
const _markers: Partial<Markers> = {
point: (data: PointData) => {
const layer = new aimap.MassMarkerLayer(this._toPoints(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,
}
// 点击覆盖物获取自定义数据
this._clickCb && this._clickCb(arg, e?.features?.[0]?.properties)
})
return layer
},
}
this._markers = Object.assign(this._markers, _markers)
}
zoomIn(options: ZoomOptions) {
this.map.zoomIn(options)
}
......@@ -133,4 +216,7 @@ export default class AI_Map extends MyMap {
...options,
})
}
remove(layer: any) {
layer.remove()
}
}
......@@ -6,12 +6,15 @@ import {
ZoomOptions,
FocusOptions,
Location,
Markers,
PointData,
} from './types'
export default abstract class MyMap {
protected map
protected _listeners: Listeners
protected _controls: Controls
protected _markers: Markers
constructor(instance: any) {
this.map = instance
......@@ -85,6 +88,9 @@ export default abstract class MyMap {
console.error('set:此地图不存在 bMapGalleryexpand 控件!')
},
}
this._markers = {
point: () => console.error('add:此地图不存在 point 撒点!'),
}
}
/**
......@@ -117,6 +123,15 @@ export default abstract class MyMap {
return this
}
/**
* 添加覆盖物
* @param type 覆盖物类型
* @param data 覆盖物数据
*/
add<K extends keyof Markers>(type: K, data: PointData) {
return this._markers[type](data)
}
/**
* zoom in
* @param options 参数
......@@ -139,4 +154,10 @@ export default abstract class MyMap {
* @param options 参数
*/
abstract focus(location: Location, options?: FocusOptions): unknown
/**
* 移除覆盖物
* @param layer 覆盖物
*/
abstract remove(layer: unknown): void
}
......@@ -8,6 +8,9 @@ import {
FocusOptions,
Controls,
SMapConfig,
Markers,
PointData,
ClickCallBack,
} from './types'
declare const SMap: {
......@@ -17,6 +20,7 @@ declare const SMap: {
Icon: any
Label: any
Marker: any
OverlayGroup: any
Network: any
Home: any
Zoom: any
......@@ -54,9 +58,11 @@ export default class S_Map extends MyMap {
super(instance)
this._setListeners()
this._setControls()
this._setMarkers()
this.on('load', this._clearFooter)
}
/** 清除地图自带的脚注 */
private _clearFooter() {
const footer = document.querySelector(
'.esri-ui-manual-container>.esri-component',
......@@ -64,6 +70,7 @@ export default class S_Map extends MyMap {
footer && ((footer as HTMLElement).style.display = 'none')
}
/** 设置监听事件 */
private _setListeners() {
const _listeners: Partial<Listeners> = {
load: (cb: CallBack) => {
......@@ -100,7 +107,8 @@ export default class S_Map extends MyMap {
this._listeners = Object.assign(this._listeners, _listeners)
}
private _addEvent(event: unknown, cb: CallBack) {
/** 特殊的可能会带自定义数据的事件 */
private _addEvent(event: unknown, cb: ClickCallBack) {
this.map.on(event, (view: any, e: any) => {
const arg = {
type: e.type,
......@@ -108,14 +116,17 @@ export default class S_Map extends MyMap {
event: e.native,
clientX: e.x,
clientY: e.y,
x: e?.mapPoint?.x,
y: e?.mapPoint?.y,
originData: e,
}
view.hitTest(e).then((res: any) => {
cb(arg, res.results)
cb(arg, res?.results?.[0]?.graphic?.attributes || null)
})
})
}
/** 设置控制器 */
private _setControls() {
const _controls: Partial<Controls> = {
home: (options?: ControlOptions) => {
......@@ -210,6 +221,56 @@ 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,
},
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)
return layer
},
}
this._markers = Object.assign(this._markers, _markers)
}
zoomIn() {
this.map.zoomIn()
}
......@@ -223,4 +284,7 @@ export default class S_Map extends MyMap {
const level = options?.zoom || this.map.getZoom()
this.map.setZoomAndCenter(level, location)
}
remove(layer: unknown) {
this.map.remove(layer)
}
}
......@@ -48,6 +48,15 @@ export type AIMapConfig = {
export type Location = [number, number] | [number, number, number]
/**
* 坐标系类型
* @param gcj02 高德坐标系
* @param wgs84 gps坐标系
* @param bd09 百度坐标系
* @param cgcs2000 城建坐标系
*/
export type LocationType = 'gcj02' | 'wgs84' | 'bd09' | 'cgcs2000'
/**
* 监听回调函数
*/
......@@ -66,6 +75,10 @@ export type ClickCallBack = (
clientX: number
/** 触发时鼠标y位置 */
clientY: number
/** 鼠标点击x坐标 */
x?: number
/** 鼠标点击y坐标 */
y?: number
/** 地图触发事件的原始数据(即未经封装前的数据) */
originData: any
},
......@@ -149,3 +162,38 @@ export interface FocusOptions {
/** 整个fly动画持续毫秒时间(默认3000) */
maxDuration?: number
}
export interface Markers {
point: (data: PointData) => unknown
}
/**
* 点状覆盖物数据
*/
export interface PointData {
data: {
id?: string
x?: number
y?: number
z?: number
X?: number
Y?: number
Z?: number
gpsx?: number
gpsy?: number
gpsz?: number
icon?: string
spatialReference?: LocationType
[key: string]: any
}[]
size?: number | [number, number]
icon?: string
spatialReference?: LocationType
labelKey?: string
labelOptions?: {
size?: number
/** [水平偏移量,垂直偏移量] */
offset?: [number, number] | [number, number, number]
color?: string
}
}
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