Commit 44ca7df6 authored by 郭铭瑶's avatar 郭铭瑶 🤘

添加地图组件

parent 54ca3f09
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
<body> <body>
<div id="app"></div> <div id="app"></div>
<script src="/shanghaiwuye_gis_map_api_3.2.210421/SMap.min.js"></script>
<script src="/shanghaiwuye_gis_map_api_3.2.210421/Plugins.min.js"></script>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
......
# smap-xh
上海市测绘院地图API加载库,通过该API库实现上海测绘院地图数据加载显示(仅限上海市徐汇行政服务中心政务网可用)
## 注意事项
由于smap-xh 属于新版本api,同时支持二三维一体化,目前功能还不完善,内容同步更新中。
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/xh/map3d.png)
## 目录
- [安装](#安装)
- [使用](#使用)
- [以NPM包方式使用](#以NPM包方式使用)
- [以普通JS方式使用](#以普通JS方式使用)
- [示例](#示例)
- [地图](#地图)
- [生命周期](#生命周期)
- [设置网络模式](#设置网络模式)
- [创建二维地图](#创建二维地图)
- [创建三维地图](#创建三维地图)
- [地图样式](#地图样式)
- [地图样式-默认样式](#地图样式-默认样式)
- [地图样式-暗色样式](#地图样式-暗色样式)
- [地图样式-实景样式](#地图样式-实景样式)
- [业务图层开关](#业务图层开关)
- [业务数据名称(不断更新)](#业务数据名称(不断更新))
- [显示业务数据](#显示业务数据)
- [隐藏业务数据](#隐藏业务数据)
- [设置图层筛选条件](#设置图层筛选条件)
- [地图属性](#地图属性)
- [地图缩放级别控制](#地图缩放级别zooms控制)
- [地图是否可旋转](#地图是否可旋转)
- [三维建筑地块是否可见](#三维建筑地块是否可见)
[获取三维地图俯仰角](#[获取三维地图俯仰角)
- [设置三维地图俯仰角](#设置三维地图俯仰角)
- [获取地图中心点](#获取地图中心点)
- [获取地图级别](#获取地图级别)
- [设置地图中心点](#设置地图中心点)
- [设置地图级别](#设置地图级别)
- [设置地图级别和中心点](#设置地图级别和中心点)
- [获取地图比例尺](#获取地图比例尺)
- [设置地图旋转角度](#设置地图旋转角度)
- [获取地图显示范围](#获取地图显示范围)
- [设置地图显示范围](#设置地图显示范围)
- [地图平移-像素平移](#地图平移-像素平移)
- [地图平移-中心点平移](#地图平移-中心点平移)
- [地图放大](#地图放大)
- [地图放大](#地图缩小)
- [设置地图样式](#设置地图样式)
- [获取地图样式](#获取地图样式)
- [开启穿透地表](#开启穿透地表)
- [恢复地表模式](#恢复地表模式)
- [添加地图缩放范围限制](#添加地图缩放范围限制)
- [移除地图缩放范围限制](#移除地图缩放范围限制)
- [鼠标禁用](#鼠标禁用)
- [3d模式下二三维视角切换](#3d模式下二三维视角切换)
- [添加图层](#添加图层)
- [根据服务url添加图层](#根据服务url添加图层)
- [根据图层id获取图层](#根据图层id获取图层)
- [设置图层属性](#设置图层属性)
- [根据图层id删除图层](#根据图层id删除图层)
- [自定义地图控件主题](#自定义地图控件主题)
- [自定义地图控件主题-暗色主题](#自定义地图控件主题-暗色主题)
- [自定义地图控件主题-亮色主题](#自定义地图控件主题-亮色主题)
- [地图控件](#地图控件)
- [地图控件-Home](#地图控件-Home)
- [地图控件-Zoom](#地图控件-Zoom)
- [地图控件-Compass](#地图控件-Compass)
- [地图控件-Fullscreen](#地图控件-Fullscreen)
- [地图控件-LayerListControl](#地图控件-LayerListControl)
- [地图控件-MeasureLine](#地图控件-MeasureLine)
- [地图控件-MeasureArea](#地图控件-MeasureArea)
- [地图控件-BasemapToggle](#地图控件-BasemapToggle)
- [地图控件-UndergroundSwitch](#地图控件-UndergroundSwitch)
- [地图控件-BMapGallery](#地图控件-BMapGallery)
- [地图控件-BMapGalleryExpand](#地图控件-BMapGalleryExpand)
- [删除地图控件](#删除地图控件)
- [地图覆盖物](#地图覆盖物)
- [添加点状覆盖物](#添加点状覆盖物)
- [更新点状覆盖物](#更新点状覆盖物)
- [删除点状覆盖物](#删除点状覆盖物)
- [添加点状覆盖物多个](#添加点状覆盖物多个)
- [更新点状覆盖物多个](#更新点状覆盖物多个)
- [删除点状覆盖物多个](#删除点状覆盖物多个)
- [添加点状覆盖物组](#添加点状覆盖物组)
- [更新点状覆盖物组](#更新点状覆盖物组)
- [删除点状覆盖物组](#删除点状覆盖物组)
- [添加线状覆盖物](#添加线状覆盖物)
- [更新线状覆盖物](#更新线状覆盖物)
- [删除线状覆盖物](#删除线状覆盖物)
- [添加线状覆盖物多个](#添加线状覆盖物多个)
- [更新线状覆盖物多个](#更新线状覆盖物多个)
- [删除线状覆盖物多个](#删除线状覆盖物多个)
- [添加线状覆盖物组](#添加线状覆盖物组)
- [更新线状覆盖物组](#更新线状覆盖物组)
- [删除线状覆盖物组](#删除线状覆盖物组)
- [添加面状覆盖物](#添加面状覆盖物)
- [更新面状覆盖物](#更新面状覆盖物)
- [删除面状覆盖物](#删除面状覆盖物)
- [添加面状覆盖物多个](#添加面状覆盖物多个)
- [更新面状覆盖物多个](#更新面状覆盖物多个)
- [删除面状覆盖物多个](#删除面状覆盖物多个)
- [添加面状覆盖物组](#添加面状覆盖物组)
- [更新面状覆盖物组](#更新面状覆盖物组)
- [删除面状覆盖物组](#删除面状覆盖物组)
- [地图覆盖物More](#地图覆盖物More)
- [添加点状覆盖物](#添加点状覆盖物addfeature)
- [更新点状覆盖物](#更新点状覆盖物updatefeature)
- [删除点状覆盖物](#删除点状覆盖物removefeature)
- [添加点状覆盖物多个](#添加点状覆盖物多个addfeature)
- [更新点状覆盖物](#更新点状覆盖物多个updatefeature)
- [删除点状覆盖物多个](#删除点状覆盖物多个removefeature)
- [添加点状覆盖物组](#添加点状覆盖物组addfeature)
- [更新点状覆盖物组](#更新点状覆盖物组updatefeature)
- [删除点状覆盖物组](#删除点状覆盖物组removefeature)
- [地图事件](#地图事件)
- [地图事件列表](#地图事件列表)
- [地图zoom变化事件](#地图zoom变化事件)
- [地图加载完成事件](#地图加载完成事件)
- [地图范围变化事件](#地图范围变化事件)
- [地图中心点变化事件](#地图中心点变化事件)
- [地图失去焦点事件](#地图失去焦点事件)
- [地图单击事件](#地图单击事件)
- [地图双击事件](#地图双击事件)
- [地图拖拽事件](#地图拖拽事件)
- [地图聚焦事件](#地图聚焦事件)
- [地图按住事件](#地图按住事件)
- [地图键盘键按下事件](#地图键盘键按下事件)
- [地图键盘键弹起事件](#地图键盘键弹起事件)
- [地图鼠标和触摸滚动事件](#地图鼠标和触摸滚动事件)
- [地图鼠标或触摸按下事件](#地图鼠标或触摸按下事件)
- [地图鼠标进入或触摸开始事件](#地图鼠标进入或触摸开始事件)
- [地图鼠标离开和触摸结束事件](#地图鼠标离开和触摸结束事件)
- [地图鼠标移动和触摸操作事件](#地图鼠标移动和触摸操作事件)
- [地图鼠标释放和触摸结束事件](#地图鼠标释放和触摸结束事件)
- [地图控件大小变化事件](#地图控件大小变化事件)
## 安装
```bash
npm install smap-xh --save
```
## 使用
### [以NPM包方式使用]
```js
import SMap from 'smap-xh'
const map = new SMap.Map('container', {
viewMode: '3D',
center: [0, 0],
zoom: 5,
zooms: [1, 12],
pitch: 60,
mapStyle: 'smap://styles/dark', // 'smap://styles/normal' 'smap://styles/image'
showBuildingBlock: true,
appKey: '**********' // appkey
})
```
### [以普通JS方式使用]
```js
<script src="http://10.201.37.225:8080/smiapi/smap/SMap.min.js">
const smap = new SMap.Map('mapcontainer', {
viewMode: '2D',
center: [0, 0],
zoom: 5,
zooms: [1, 12],
mapStyle: 'smap://styles/dark', // 'smap://styles/normal' 'smap://styles/image'
})
```
## 示例
### [地图]
#### [生命周期]
##### [设置网络模式]
```js
import SMap from 'smap-xh'
new SMap.Network().setNet(网络参数);
```
##### [创建二维地图]
```js
import SMap from 'smap-xh'
const map = new SMap.Map('container', {
center: [0, 0],
zoom: 5
})
```
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/2d/%E5%9C%B0%E5%9B%BE/%E5%9C%B0%E5%9B%BE%E5%88%9B%E5%BB%BA/mapcreate.png)
##### [创建三维地图]
```js
import SMap from 'smap-xh'
const map = new SMap.Map('container', {
viewMode: '3D',
center: [0, 0],
zoom: 4,
pitch:60
})
```
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/3d/%E5%9C%B0%E5%9B%BE/%E5%9C%B0%E5%9B%BE%E5%88%9B%E5%BB%BA/mapcreate.png)
#### [地图样式]
##### [地图样式-默认样式]
```js
const map = new SMap.Map('container', {
viewMode: '2D',
center: [0, 0],
zoom: 4,
mapStyle: 'smap://styles/normal' //为赋值时候,默认为smap://styles/normal
})
```
##### [地图样式-暗色样式]
```js
const map = new SMap.Map('container', {
viewMode: '2D',
center: [0, 0],
zoom: 4,
mapStyle: 'smap://styles/dark'
})
```
##### [地图样式-实景样式]
```js
const map = new SMap.Map('container', {
viewMode: '2D',
center: [0, 0],
zoom: 4,
mapStyle: 'smap://styles/image'
})
```
#### [业务图层开关]
##### [业务数据名称(不断更新)]
```js
//"wg_gis_xq_point"为小区点,
//"wg_gis_xq_poly"为小区面,
//"wg_gis_zb_jkd"为小区健康度
//"wg_gis_mpz"为门牌幢点,
//"wg_gis_elevator"为电梯点,
//"wg_gis_sensor"为传感器
```
##### [显示业务数据]
```js
map.getLayer("wg_gis_xq_point").visible = true;//参数为业务数据名称
```
##### [隐藏业务数据]
```js
map.getLayer("wg_gis_xq_point").visible = false;//参数为业务数据名称
```
##### [设置图层筛选条件]
```js
//第一个参数为业务数据名称:
//第二个参数为筛选条件,与属性表对应正确的条件即可
this.map.setFilter("wg_gis_xq_point", "HPB_NAME = '黄浦区' or HPB_NAME = '虹口区' or HPB_NAME = '普陀区'");
this.map.setFilter("wg_gis_mpz", "HPB_NAME = '黄浦区' or HPB_NAME = '虹口区'");
this.map.setFilter("wg_gis_xq_poly", "HPB_NAME = '黄浦区'");
this.map.setFilter("wg_gis_elevator", "HPB_NAME = '黄浦区'");
this.map.setFilter("wg_gis_sensor", "SENSOR_TYPE_NAME = '智能水表'");
```
#### [地图属性]
##### [地图缩放级别zooms控制]
```js
const map = new SMap.Map('container', {
center: [0, 0],
zoom: 5,
zooms: [1, 9] //二三维都支持,默认最新小0,最大10 建议二维默认设置最小1,最大9
})
```
##### [地图是否可旋转]
```js
const map = new SMap.Map('container', {
center: [0, 0],
zoom: 5,
zooms: [1, 9]
rotateEnable: false //暂二维支持
})
```
##### [三维建筑地块是否可见]
```js
const map = new SMap.Map('container', {
center: [0, 0],
zoom: 5,
zooms: [1, 9]
showBuildingBlock: false, //三维地图可用,未赋值时候默认为true
})
```
##### [获取三维地图俯仰角]
```js
const pitch= map.getPitch()
```
##### [设置三维地图俯仰角]
```js
map.setPitch(30)
```
##### [获取地图中心点]
```js
const mapcenter = map.getCenter()
```
##### [获取地图级别]
```js
const zoom = map.getZoom()
```
##### [设置地图中心点]
```js
//2D
map.setCenter(00)
//3D
map.setCenter(00, 0)
```
##### [设置地图级别]
```js
map.setZoom(10)
```
##### [设置地图级别和中心点]
```js
//2D
map.setZoomAndCenter(10[0, 0])
//3D
map.setZoomAndCenter(10[0, 0, 0])
```
##### [获取地图比例尺]
```js
map.getScale()
```
##### [设置地图旋转角度]
```js
map.setRotation(90)
```
##### [获取地图显示范围]
```js
const bounds = map.getBounds()
```
##### [设置地图显示范围]
```js
//2D
const mybounds = new SMap.Bounds([-12244.941157, -6531.252646], [13155.109644,5811.584540]);
map.setBounds(mybounds);
//3D
const mybounds = new SMap.Bounds([-12244.941157, -6531.252646], [13155.109644,5811.584540]);
OR
const mybounds = new SMap.Bounds([-12244.941157, -6531.252646, 0], [13155.109644,5811.584540, 0]);
map.setBounds(mybounds);
```
##### [地图平移-像素平移]
```js
map.panBy(50, 100)
```
##### [地图平移-中心点平移]
```js
//2D
map.panTo(0, 0)
//3D
map.panTo(0, 0, 0) OR map.panTo(0, 0)
```
##### [地图放大]
```js
map.zoomIn()
```
##### [地图缩小]
```js
map.zoomOut()
```
##### [设置地图样式]
```js
map.setMapStyle('smap://styles/normal')
```
##### [获取地图样式]
```js
map.getMapStyle()
```
##### [开启穿透地表]
```js
map.enableThroughGround(true)
```
##### [恢复地表模式]
```js
map.enableThroughGround(false)
```
##### [添加地图缩放范围限制]
```js
this.map.setExtentConstrain([0, 0], [1000, 1000])
```
##### [移除地图缩放范围限制]
```js
map.removeExtentConstrain()
```
##### [鼠标禁用]
```js
map.enableMouseEvent(fasle)
```
##### [3d模式下二三维切换]
```js
map.switchMode('2d') //map.switchMode('3d')
```
#### [添加图层]
##### [根据服务url添加图层]
```js
layerType // 图层类型 MapImageLayer SceneLayer FeatureLayer TileLayer GraphicsLayer SHCTiledMapServiceLayer
layerUrl // 服务URl
isToken // 服务isToken
layerTitle // 服务title
layerId // 服务layerId
layerOpacity // 服务opacity
layerVisible // 服务visible
layerLabelsVisible // 服务labelsVisible 支持FeatureLayer
layerLabelingInfo // 服务labelingInfo 支持FeatureLayer
layerMaxScale // 服务maxScale
layerMinScale // 服务minScale
layerdefinitionExpression //服务过滤条件
layerelevationInfo // elevationInfo 支持FeatureLayer SceneLayer GraphicsLayer
layerPopupEnabled // 服务popupEnabled 支持FeatureLayer SceneLayer GraphicsLayer
layerPopupTemplate// 服务popupTemplate 支持FeatureLayer SceneLayer GraphicsLayer
layerRenderer // 服务renderer
layerSublayers // sublayers 支持支持MapImageLayer
```
```js
const SceneLayerparam = {
layerType: 'SceneLayer',
layerUrl: "http://10.201.37.220/server/rest/services/Hosted/LBJZ_ORIGIN/SceneServer",
layerTitle: "历保建筑原貌",
layerLayerId: "LBJZ_ORIGIN",
layerOpacity:1,
layerVisible:true,
layerMaxScale:1000,
layerMinScale:10000000,
layerPopupEnabled:true,
elevationInfo: {
mode: 'absolute-height',
offset: -2.5
}
}
this.map.addLayer(SceneLayerparam)
```
##### [根据图层id获取图层]
```js
smap.getLayer('LBJZ_ORIGIN')
```
##### [设置图层属性]
```js
layerId // 服务layerId
layerTitle // 服务title
layerOpacity // 服务opacity
layerVisible // 服务visible
layerLabelsVisible // 服务labelsVisible 支持FeatureLayer
layerLabelingInfo // 服务labelingInfo 支持FeatureLayer
layerMaxScale // 服务maxScale
layerMinScale // 服务minScale
layerdefinitionExpression //服务过滤条件
layerelevationInfo // elevationInfo 支持FeatureLayer SceneLayer GraphicsLayer
layerPopupEnabled // 服务popupEnabled 支持FeatureLayer SceneLayer GraphicsLayer
layerPopupTemplate// 服务popupTemplate 支持FeatureLayer SceneLayer GraphicsLayer
layerRenderer // 服务renderer
layerSublayers // sublayers 支持支持MapImageLayer
```
```js
const Layerpasrams = {
layerLayerId: "LBJZ_ORIGIN",
layerVisible:false
}
this.map.setLayerProperties(Layerpasrams) //修改图层LBJZ_ORIGIN的可见性为false
```
##### [根据图层id删除图层]
```js
smap.removeLayer('LBJZ_ORIGIN')
```
#### [自定义地图控件主题]
##### [自定义地图控件主题-暗色主题]
```js
<div id="container" class="calcite-map calcite-widgets-dark" />
```
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/3d/%E5%9C%B0%E5%9B%BE%E4%B8%BB%E9%A2%98/maptheme_dark.png)
###### [自定义地图控件主题-亮色主题]
```js
<div id="container" class="calcite-map calcite-widgets-light" />
注意:开发者可以自定义
```
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/3d/%E5%9C%B0%E5%9B%BE%E4%B8%BB%E9%A2%98/maptheme_light.png)
#### [地图控件]
##### [地图控件-Home]
```js
const home = new SMap.Home({
visible: true,
position: 'top-right'
})
map.addControl(home)
```
##### [地图控件-Zoom]
```js
const zoom = new SMap.Zoom({
visible: true,
position: 'top-right'
})
map.addControl(zoom)
```
##### [地图控件-Compass]
```js
const compass = new SMap.Compass({
visible: true,
position: 'top-right'
})
map.addControl(ccompass))
```
##### [地图控件-Fullscreen]
```js
const fullfscreen = new SMap.Fullscreen({
visible: true,
position: 'top-right'
})
map.addControl(fullfscreen))
```
##### [地图控件-LayerListControl]
```js
const layerListControl = new SMap.LayerListControl({
visible: true,
position: 'top-right'
})
map.addControl(lalyerListControl))
```
##### [地图控件-MeasureLine]
```js
const measureLine = new SMap.MeasureLine({
visible: true,
position: 'top-right'
})
map.addControl(measureLine))
```
##### [地图控件-MeasureLine]
```js
const measureArea = new SMap.MeasureArea({
visible: true,
position: 'top-right'
})
map.addControl(measureArea))
```
##### [地图控件-MeasureLine]
```js
const basemapToggle = new SMap.BasemapToggle({
visible: true,
position: 'top-right'
})
map.addControl(basemapToggle))
```
##### [地图控件-UndergroundSwitch]
```js
// 仅支持3D地图
const underguroundSwitch = new SMap.UndergroundSwitch({
visible: true,
position: 'top-right'
})
map.addControl(underguroundSwitch))
```
##### [地图控件-BMapGallery]
```js
// 支持2/3D地图
const bMapGallery = new SMap.BMapGallery({
visible: true,
position: 'top-right'
})
map.addControl(bMapGallery))
```
##### [地图控件-BMapGalleryExpand]
```js
// 支持2/3D地图
const bMapGalleryexpand = new SMap.BMapGalleryExpand({
visible: true,
position: 'top-right'
})
map.addControl(bMapGalleryexpand))
```
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/2d/%E5%9C%B0%E5%9B%BE%E6%8E%A7%E4%BB%B6/mapcontrols.png)
##### [删除地图控件]
```js
map.removeControl(layerListControl)) //删除已经添加的layerListControl控件
```
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/3d/%E5%9C%B0%E5%9B%BE%E6%8E%A7%E4%BB%B6/mapcontrol.png)
#### [地图覆盖物]
##### [添加点状覆盖物]
```js
const Pointmarker = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(22, 22),
image: require('../assets/repaireorder_Accepted.gif') //或者用url
}),
attributes: {
'name': '点1',
'type': '点'
},
label: new SMap.Label({
text: '点1',
color: 'red',
visible: true,
size: 22,
weight: 'normal',
angle: 0,
backgroundColor: 'red',
borderLineColor: 'blue',
borderLineSize: 1,
haloColor: '[51, 204, 51, 0.2]',
haloSize: 0,
horizontalAlignment: 'left',
verticalAlignment: 'top',
kerning: true,
lineHeight: 25,
lineWidth: 200,
rotated: false,
xoffset: 10,
yoffset: 10
}),
position: [0, 0]
})
map.add(Pointmarker)
```
##### [更新点状覆盖物]
```js
Pointmarker.label.text = '点1更新'
Pointmarker.icon.image = require('../assets/blue.gif')
map.update(Pointmarker)
```
##### [删除点状覆盖物]
```js
map.remove(Pointmarker) //移除上面添加的点状覆盖物
```
##### [添加点状覆盖物多个]
```js
const Pointmarker1 = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(22, 22),
image: require('../assets/repaireorder_Accepted.gif') //或者用url
}),
attributes: {
'name': '点1',
'type': '点'
},
label: new SMap.Label({
text: '点1',
}),
position: [1000, 1000]
})
const Pointmarker2 = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(22, 22),
image: require('../assets/repaireorder_Accepted.gif') //或者用url
}),
attributes: {
'name': '点2',
'type': '点'
},
label: new SMap.Label({
text: '点2',
}),
position: [1100, 1100]
})
map.add([Pointmarker1,Pointmarker2])
```
##### [更新点状覆盖物多个]
```js
Pointmarker1.label.text = '点1更新'
Pointmarker1.icon.image = require('../assets/blue.gif')
Pointmarker2.label.text = '点2更新'
Pointmarker2.icon.image = require('../assets/blue.gif')
map.update([Pointmarker1, Pointmarker2])
```
##### [删除点状覆盖物多个]
```js
map.remove([Pointmarker1,Pointmarker2]) //移除上面添加的Pointmarker1,Pointmarker2点状覆盖物
```
##### [添加点状覆盖物组]
```js
const marker1 = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(40, 40),
image: require('../assets/blue.gif')
}),
attributes: {
'name': '点1',
'type': '点'
},
label: new SMap.Label({
text: '点1',
size: 22,
color: 'yellow',
xoffset: 0.1,
yoffset: 0.1,
// zoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
}),
position: [500, 500, 100]
})
const marker2 = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(40, 40),
image: require('../assets/blue.gif')
}),
attributes: {
'name': '点2',
'type': '点'
},
label: new SMap.Label({
text: '点2',
size: 22,
color: 'black',
xoffset: 0.1,
yoffset: 0.1,
// zoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
}),
position: [550, 550, 200]
})
const OverlayGroup = new SMap.OverlayGroup([marker1, marker2])
map.add(OverlayGroup)
```
##### [更新点状盖盖物组]
```js
OverlayGroup.overlayers[0].icon.image = require('../assets/repaireorder_Accepted.gif')
OverlayGroup.overlayers[0].label.text = '点5更新'
OverlayGroup.overlayers[1].icon.image = require('../assets/repaireorder_Accepted.gif')
OverlayGroup.overlayers[1].label.text = '点6更新'
map.update(OverlayGroup)
```
##### [删除点状覆盖物组]
```js
map.remove(OverlayGroup)
```
##### [添加线状覆盖物]
```js
onePolyline = new SMap.Polyline({
path: [
new SMap.LngLat(0, 0),
new SMap.LngLat(10, 10),
new SMap.LngLat(50, 50)
],
attributes: {
'name': '线1',
'type': '线'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '线一',
color: 'red',
visible: true,
size: 22,
weight: 'normal',
angle: 0,
backgroundColor: 'red',
borderLineColor: 'blue',
borderLineSize: 10,
haloColor: '[51, 204, 51, 0.2]',
haloSize: 0,
horizontalAlignment: 'left',
verticalAlignment: 'top',
kerning: true,
lineHeight: 25,
lineWidth: 200,
rotated: false,
xoffset: 10,
yoffset: 10
})
})
map.add(onePolyline)
```
##### [更新线状覆盖物]
```js
onePolyline.label.text = '线一更新'
map.update(onePolyline)
```
##### [删除线状覆盖物]
```js
map.remove(onePolyline) //移除上面添加的线状覆盖物
```
##### [添加线状覆盖物多个]
```js
const Polyline1 = new SMap.Polyline({
path: [
new SMap.LngLat(400, 400),
new SMap.LngLat(420, 420),
new SMap.LngLat(450, 450)
],
attributes: {
'name': '线1',
'type': '线'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '线一',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
const Polyline2 = new SMap.Polyline({
path: [
new SMap.LngLat(600, 600),
new SMap.LngLat(620, 620),
new SMap.LngLat(650, 650)
],
attributes: {
'name': '线1',
'type': '线'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '线二',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
map.add([Polyline1, Polyline2])
```
##### [更新线状覆盖物多个]
```js
Polyline1.label.text = '线一更新'
Polyline2.label.text = '线二更新'
map.update([Polyline1, Polyline2])
```
##### [删除线状覆盖物多个]
```js
map.remove([Polyline1,Polyline1]) //移除上面添加的Pointmarker1fourPolyline点状覆盖物
```
##### [添加线状覆盖物组]
```js
const polyline1 = new SMap.Polyline({
path: [
new SMap.LngLat(400, 400),
new SMap.LngLat(420, 420),
new SMap.LngLat(450, 450)
],
attributes: {
'name': '线1',
'type': '线'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '线1',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
const polyline2 = new SMap.Polyline({
path: [
new SMap.LngLat(300, 300),
new SMap.LngLat(320, 320),
new SMap.LngLat(350, 350)
],
attributes: {
'name': '线2',
'type': '线'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '线2',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
OverlayGroup = new SMap.OverlayGroup([polyline1, polyline2])
map.add(OverlayGroup)
```
##### [更新线状覆盖物组]
```js
OverlayGroup.overlayers[0].label.text = '线1更新'
OverlayGroup.overlayers[1].label.text = '线2更新'
map.update(OverlayGroup)
```
##### [删除线状覆盖物组]
```js
map.remove(OverlayGroup)
```
##### [添加面状覆盖物]
```js
onePolygon = new SMap.Polygon({
paths: [
new SMap.LngLat(0, 0),
new SMap.LngLat(20, 0),
new SMap.LngLat(20, 30),
new SMap.LngLat(0, 30),
new SMap.LngLat(0, 0)
],
attributes: {
'name': '面1',
'type': '面'
},
fillColor: 'red',
style: 'solid',
strokeColor: 'yellow',
strokestyle: 'solid',
strokeWeight: 1,
label: new SMap.Label({
text: '面一',
color: 'red',
visible: true,
size: 22,
weight: 'normal',
angle: 0,
backgroundColor: 'red',
borderLineColor: 'blue',
borderLineSize: 10,
haloColor: '[51, 204, 51, 0.2]',
haloSize: 0,
horizontalAlignment: 'left',
verticalAlignment: 'top',
kerning: true,
lineHeight: 25,
lineWidth: 200,
rotated: false,
xoffset: 10,
yoffset: 10
})
})
map.add(onePolygon)
```
##### [更新面状覆盖物]
```js
onePolygon.label.text = '面一更新'
map.update(onePolygon)
```
##### [删除面状覆盖物]
```js
map.remove(onePolygon) //移除上面添加的面状覆盖物
```
##### [添加面状覆盖物多个]
```js
const Polygon1 = new SMap.Polygon({
paths: [
new SMap.LngLat(540, 540),
new SMap.LngLat(560, 540),
new SMap.LngLat(560, 560),
new SMap.LngLat(540, 560),
new SMap.LngLat(540, 540)
],
attributes: {
'name': '面1',
'type': '面'
},
fillColor: 'red',
style: 'solid',
strokeColor: 'yellow',
strokestyle: 'solid',
strokeWeight: 1,
label: new SMap.Label({
text: '面1',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
const Polygon2 = new SMap.Polygon({
paths: [
new SMap.LngLat(500, 500),
new SMap.LngLat(520, 500),
new SMap.LngLat(520, 550),
new SMap.LngLat(500, 550),
new SMap.LngLat(500, 500)
],
attributes: {
'name': '面2',
'type': '面'
},
fillColor: 'black',
style: 'solid',
strokeColor: 'yellow',
strokestyle: 'solid',
strokeWeight: 1,
label: new SMap.Label({
text: '面2',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
map.add([Polygon1, Polygon2])
```
##### [更新面状覆盖物多个]
```js
Polygon1.label.text = '面一更新'
Polygon2.label.text = '面二更新'
map.update([Polygon1, Polygon2])
```
##### [删除面状覆盖物多个]
```js
map.remove([Polygon1,Polygon2]) //移除上面添加的Polygon1 Polygon2 面状状覆盖物
```
##### [添加面状覆盖物组]
```js
const polygon1 = new SMap.Polygon({
paths: [
new SMap.LngLat(200, 200),
new SMap.LngLat(220, 200),
new SMap.LngLat(220, 250),
new SMap.LngLat(200, 250),
new SMap.LngLat(200, 200)
],
attributes: {
'name': '面1',
'type': '面'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '面1',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
const polygon2 = new SMap.Polygon({
paths: [
new SMap.LngLat(240, 240),
new SMap.LngLat(260, 240),
new SMap.LngLat(260, 260),
new SMap.LngLat(240, 260),
new SMap.LngLat(240, 240)
],
attributes: {
'name': '面2',
'type': '面'
},
cap: 'square',
strokeColor: 'red',
style: 'solid',
lineJoin: 'round',
label: new SMap.Label({
text: '面2',
size: 22,
color: 'blue',
xoffset: 10,
yoffset: 10,
horizontalAlignment: 'left',
verticalAlignment: 'top'
})
})
OverlayGroup = new SMap.OverlayGroup([polygon1, polygon2])
map.add(OverlayGroup)
```
##### [更新面状覆盖物组]
```js
OverlayGroup.overlayers[0].label.text = '面1更新'
OverlayGroup.overlayers[1].label.text = '面2更新'
map.update( OverlayGroup)
```
##### [删除面状覆盖物组]
```js
map.remove(OverlayGroup)
```
#### [地图覆盖物More]
##### [添加点状覆盖物addfeature]
```js
const onemarker = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(40, 40),
image: require('../assets/repaireorder_Accepted.gif')
}),
attributes: { //点状覆盖物的属性
'name': '点1', //如果需要标注 name 字段必须有,且其字段值为标注内容
'type': '点'
},
label: new SMap.Label({
color: 'red', //标注颜色
visible: true, //标注是否可见
size: 22, // 标注字体大小
weight: 'normal', //仅2d 支持
angle: 0, // 仅2d 支持
backgroundColor: 'red', // 仅2d 支持
borderLineColor: 'blue', // 仅2d 支持
borderLineSize: 1, // 仅2d 支持
haloColor: '[51, 204, 51, 0.2]', // 标注光圈颜色
haloSize: 0, // 标注光圈大小
horizontalAlignment: 'left', // 仅2d 支持
verticalAlignment: 'top', // 仅2d 支持
kerning: true, // 仅2d 支持
lineHeight: 0, // 仅2d 支持
lineWidth: 0, // 仅2d 支持
rotated: true, // 仅2d 支持
xoffset: 0, // 仅2d 支持
yoffset: 0, // 仅2d 支持
placement: 'above-right' //标注位置
maxScale: 500 // 最大可见比例尺
minScale: 100000 //最小可见比例尺
}),
position: [0, 0, 100]
})
map.addfeature(onemarker)
这种方式自定义性强,资源占用多,不宜多加
```
##### [更新点状覆盖物updatefeature]
```js
onemarker.attributes['name'] = '点一更新'
onemarker.icon.image = require('../assets/blue.gif')
map.updatefeature(onemarker)
```
##### [删除点状覆盖物removefeature]
```js
map.removefeature(onemarker)
```
##### [添加点状覆盖物多个addfeature]
```js
const markone = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(40, 40),
image: require('../assets/repaireorder_Accepted.gif')
}),
attributes: {
'name': '点1',
'type': '点'
},
label: new SMap.Label({
text: '点1',
size: 22,
xoffset: 0,
yoffset: 0,
horizontalAlignment: 'left',
verticalAlignment: 'top'
}),
position: [1000, 1000, 10]
})
const marktwo = new SMap.Marker({
icon: new SMap.Icon({
size: new SMap.Size(40, 40),
image: require('../assets/repaireorder_Accepted.gif')
}),
attributes: {
'name': '点2',
'type': '点'
},
label: new SMap.Label({
text: '点2',
size: 22,
xoffset: 0,
yoffset: 0,
horizontalAlignment: 'left',
verticalAlignment: 'top'
}),
position: [1100, 1100, 20]
})
map.addfeature([markone, marktwo])
通上面方法一样,自定义性强,资源占用多,不宜多加
```
##### [更新点状覆盖物多个updatefeature]
```js
markone.icon.image = require('../assets/blue.gif')
markone.attributes['name'] = '点一更新'
marktwo.icon.image = require('../assets/blue.gif')
marktwo.attributes['name'] = '点二更新'
map.updatefeature([markone, marktwo])
```
##### [删除点状覆盖物多个removefeature]
```js
map.removefeature([markone, marktwo])
```
##### [添加点状覆盖物组addfeature]
```js
const marks = []
for (let i = 0; i <= 100000; i++) {
const x = Math.ceil(Math.random() * 1200)
const y = Math.ceil(Math.random() * 1200)
const onemarker = new SMap.Marker({
attributes: {
'name': '点' + i, //name 字段要标注的内容
'style': Math.ceil(Math.random()).toString() //style 对应样式,对应Style 中style 值
},
position: [x, y, 100]
})
marks.push(onemarker)
}
const label = new SMap.Label({
size: 22,
color: 'black',
xoffset: 0.1,
yoffset: 0.1,
horizontalAlignment: 'left',
verticalAlignment: 'top',
minScale: 5000,
maxScale: 1000
})
const datafiled = [{ // 覆盖组字段类型
name: 'name',
alias: 'name',
type: 'string'
}]
const style = [ // 样式定义,和marks 中mark属性字段style 对应,对应不上没有样式
{
style: '0', //mark 属性字段style 为0时候的样式
size: new SMap.Size(40, 40),
url: require('../assets/repaireorder_Accepted.gif')
}, {
style: '1', //mark 属性字段style 为1时候的样式,以此类推可以多加
size: new SMap.Size(40, 40),
url: require('../assets/blue.gif')
}
]
const featureReduction = new SMap.FeatureReduction({
type: 'cluster',
clusterRadius: 100
})
massmarksgroup = new SMap.OverlayGroup(marks, {
overlaytype: 'marker',
datafiled: datafiled,
style: style,
label: label,
frreduction: featureReduction //聚集样式
})
map.addfeature(massmarksgroup)
此方法适合加载大量数据点
```
二维10万个点展示
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/2d/%E5%9C%B0%E5%9B%BE%E8%A6%86%E7%9B%96%E7%89%A9/massMarks.png)
二维10万个点聚合展示
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/2d/%E5%9C%B0%E5%9B%BE%E8%A6%86%E7%9B%96%E7%89%A9/massMarkscluster.png)
三维10万个点展示
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/3d/%E5%9C%B0%E5%9B%BE%E8%A6%86%E7%9B%96%E7%89%A9/massMarkers.png)
三维10万个优化显示
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/smiapi/ts/4x/3d/%E5%9C%B0%E5%9B%BE%E8%A6%86%E7%9B%96%E7%89%A9/massMarkersSelection.png)
##### [更新点状覆盖物组updatefeature]
```js
massmarksgroup.overlayers[0].attributes['name'] = '点5更新'
massmarksgroup.overlayers[0].attributes['style'] = '1'
massmarksgroup.overlayers[1].attributes['style'] = '0'
map.updatefeature(massmarksgroup)
```
##### [删除点状覆盖物组removefeature]
```js
map.removefeature(massmarksgroup)
```
#### [地图事件]
##### [地图事件列表]
```js
SMap.MapEvent.maploaded or 'maploaded';
SMap.MapEvent.extentchanged or'extentchanged';
SMap.MapEvent.centerchanged or 'centerchanged';
SMap.MapEvent.blur or 'blur';
SMap.MapEvent.click or 'click';
SMap.MapEvent.doubleclick or 'doubleclick';
SMap.MapEvent.drag or 'drag';
SMap.MapEvent.focus or 'focus';
SMap.MapEvent.hold or 'hold';
SMap.MapEvent.keydown or 'key-down';
SMap.MapEvent.keyup or 'key-up';
SMap.MapEvent.mousewheel or 'mouse-wheel';
SMap.MapEvent.pointerdown or 'pointer-down';
SMap.MapEvent.pointerenter or 'pointer-enter';
SMap.MapEvent.pointerleave or 'pointer-leave';
SMap.MapEvent.pointermove or 'pointer-move';
SMap.MapEvent.pointerup or 'pointer-up';
SMap.MapEvent.resize or ' pointer-up';
```
##### [地图zoom变化事件]
```js
map.on(SMap.MapEvent.zoomchanged, function(zoom) {
})
```
##### [地图加载完成事件]
```js
map.on(SMap.MapEvent.maploaded, function(view) {
})
```
##### [地图范围变化事件]
```js
map.on(SMap.MapEvent.extentchanged, function(excenter) {
})
```
##### [地图中心点变化事件]
```js
map.on(SMap.MapEvent.centerchanged, function(center) {
})
```
##### [地图失去焦点事件]
```js
map.on(SMap.MapEvent.blur, function(view,eventParamter) {
})
```
##### [地图单击事件]
```js
map.on(SMap.MapEvent.click, function(view,eventParamter) {
maview.hitTest(eventParamter).then(async function(response) {
console.log(response)
})
})
```
##### [地图双击事件]
```js
map.on(SMap.MapEvent.doubleclick, function(view,eventParamter) {
})
```
##### [地图拖拽事件]
```js
map.on(SMap.MapEvent.drag, function(view,eventParamter) {
})
```
##### [地图聚焦事件]
```js
map.on(SMap.MapEvent.focus, function(view,eventParamter) {
})
```
##### [地图按住事件]
```js
map.on(SMap.MapEvent.hold, function(view,eventParamter) {
})
```
##### [地图键盘键按下事件]
```js
map.on(SMap.MapEvent.keydown, function(view,eventParamter) {
})
```
##### [地图键盘键弹起事件]
```js
map.on(SMap.MapEvent.keydown, function(view,eventParamter) {
})
```
##### [地图键盘键弹起事件]
```js
map.on(SMap.MapEvent.hold, function(view,eventParamter) {
})
```
##### [地图鼠标和触摸滚动事件]
```js
map.on(SMap.MapEvent.mousewheel, function(view,eventParamter) {
})
```
##### [地图鼠标或触摸按下事件]
```js
map.on(SMap.MapEvent.pointerdown, function(view,eventParamter) {
})
```
##### [地图鼠标进入或触摸开始事件]
```js
map.on(SMap.MapEvent.pointerenter, function(view,eventParamter) {
})
```
##### [地图鼠标离开和触摸结束事件]
```js
map.on(SMap.MapEvent.pointerleave, function(view,eventParamter) {
})
```
##### [地图鼠标移动和触摸操作事件]
```js
map.on(SMap.MapEvent.pointermove, function(view,eventParamter) {
})
```
##### [地图鼠标释放和触摸结束事件]
```js
map.on(SMap.MapEvent.pointerup, function(view,eventParamter) {
})
```
##### [地图控件大小变化事件]
```js
map.on(SMap.MapEvent.resize, function(view,eventParamter) {
})
```
## 技术支持
QQ号: 314984468
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/contact/qq.jpg)
微信号:ioioya
![Image text](https://raw.githubusercontent.com/thiswildidea/images/master/contact/webchat.jpg)
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
new SMap.Network().setNet(网络参数);
网络参数包括以下几个值:
'internet':表示互联网2D;
'affairs':表示政务网2D;
'local3D':表示局域网3D;
'affairs3D':表示政务网3D;
'njdl':表示南京东路政务网3D;
\ No newline at end of file
...@@ -72,7 +72,7 @@ html, body ...@@ -72,7 +72,7 @@ html, body
height 100% height 100%
overflow hidden overflow hidden
font-size .1rem font-size .1rem
background url('/src/assets/images/map.png') center/100% 100% no-repeat // background url('/src/assets/images/map.png') center/100% 100% no-repeat
color #fff color #fff
.orange-count .orange-count
font-size .14rem font-size .14rem
......
...@@ -64,6 +64,7 @@ export default defineComponent({ ...@@ -64,6 +64,7 @@ export default defineComponent({
background-size cover background-size cover
background-position center background-position center
height .4rem height .4rem
z-index 1
.date .date
z-index 2 z-index 2
position absolute position absolute
......
import { MapConfig, CallBack, BoundaryOption, MarkerOption } from './types'
import Map from './map'
declare const AMap: {
Map: any
Icon: any
DistrictSearch: any
LngLat: any
Marker: any
Polygon: any
}
export default class A_Map extends Map {
constructor(config: MapConfig) {
super(new AMap.Map(config.el, config.options))
}
onLoad(cb: CallBack): void {
this.map.on('complete', cb)
}
onZoom(cb: CallBack): void {
this.map.on('zoomend', cb)
}
onMove(cb: CallBack): void {
this.map.on('mapmove', cb)
}
onBlur(): void {
throw new Error('AMap没有blur事件!')
}
onFocus(): void {
throw new Error('AMap没有focus事件!')
}
onDrag(cb: CallBack): void {
this.map.on('dragging', cb)
}
onResize(cb: CallBack): void {
this.map.on('resize', cb)
}
onClick(cb: CallBack): void {
this.map.on('click', cb)
}
onDblclick(cb: CallBack): void {
this.map.on('dblclick', cb)
}
onMousewheel(cb: CallBack): void {
this.map.on('mousewheel', cb)
}
zoomIn(): void {
this.map.zoomIn()
}
zoomOut(): void {
this.map.zoomOut()
}
hideCommunity(): void {
throw new Error('AMap没有hideCommunity方法!')
}
showCommunity(): void {
throw new Error('AMap没有showCommunity方法!')
}
filterCommunity(): void {
throw new Error('AMap没有filterCommunity方法!')
}
focus(location: number[], zoom = this.map.getZoom()): void {
this.map.setView(location, zoom)
}
addBoundary({
name,
type,
weight = 10,
color = 'rgba(51,145,255,.6)',
maskColor = [0, 17, 33, 0.9],
}: BoundaryOption): unknown {
if (!name || !type) {
throw new Error('AMap的addBoundary方法需要name参数!')
return
}
return new AMap.DistrictSearch({
extensions: 'all',
subdistrict: 0,
}).search(name, (_: unknown, result: any) => {
// 外多边形坐标数组和内多边形坐标数组
const outer = [
new AMap.LngLat(-360, 90, true),
new AMap.LngLat(-360, -90, true),
new AMap.LngLat(360, -90, true),
new AMap.LngLat(360, 90, true),
]
const holes = result.districtList[0].boundaries
const pathArray = [outer]
pathArray.push(holes)
const polygon = new AMap.Polygon({
pathL: pathArray,
//线条颜色,使用16进制颜色代码赋值。默认值为#006600
strokeColor: color,
strokeWeight: weight,
//轮廓线透明度,取值范围[0,1],0表示完全透明,1表示不透明。默认为0.9
strokeOpacity: 0.5,
//多边形填充颜色,使用16进制颜色代码赋值,如:#FFAA00
fillColor: maskColor,
//多边形填充透明度,取值范围[0,1],0表示完全透明,1表示不透明。默认为0.9
fillOpacity: 1,
//轮廓线样式,实线:solid,虚线:dashed
strokeStyle: 'solid',
})
polygon.setPath(pathArray)
this.map.add(polygon)
return polygon
})
}
private transMarkerData(option: MarkerOption): unknown[] {
const { data = [], size, icon, key } = option
return data.map((item: any) => {
let sizeProp = Array.isArray(size) ? size : [size, size]
if (item.size) {
sizeProp = Array.isArray(item.size) ? item.size : [item.size, item.size]
}
const result = {
icon: new AMap.Icon({
size: sizeProp,
image: item.icon || icon,
}),
position: [
item.X || item.x || item.gpsx || item.lon,
item.Y || item.y || item.gpsy || item.lat,
item.Z || item.z || item.gpsz || 0,
],
extData: { key, ...item },
}
return new AMap.Marker(result)
})
}
addMarkers(option: MarkerOption): unknown {
const markers = this.transMarkerData(option)
this.map.add(markers)
return markers
}
remove(markers: unknown): void {
this.map.remove(markers)
}
}
import MyMap from '../my-map'
import {
CallBack,
MapConfig,
Listeners,
ControlOptions,
ZoomOptions,
FocusOptions,
Location,
ClickCallBack,
Controls,
AIMapConfig,
Layers,
LayerOption,
} from '../types'
import { toLines, toPoints, toPolygons } from './util'
/** 维智地图 */
export default class AI_Map extends MyMap {
private _clickCb: ClickCallBack | null = null
constructor(config: MapConfig<AIMapConfig>) {
if (!config.appKey) {
throw new Error('AIMap需要设置appKey参数!')
}
aimap.accessToken = config.appKey
if (!config.baseApiUrl) {
throw new Error('AIMap需要设置baseApiUrl参数!')
}
aimap.baseApiUrl = config.baseApiUrl
const instance = new aimap.Map({
container: config.el,
center: config.center,
zoom: config.zoom,
minZoom: config.zooms?.[0],
maxZoom: config.zooms?.[1],
pitch: config.pitch || 0,
minPitch: config.pitchs?.[0],
maxPitch: config.pitchs?.[1],
bearing: config.bearing || 0,
style: config.style,
localIdeographFontFamily: config.family,
})
super(instance)
this._setListeners()
this._setControls()
this._setLayers()
}
/** 设置监听事件 */
private _setListeners() {
const _listeners: Partial<Listeners> = {
load: (cb: CallBack) => {
this.map.on('load', cb)
},
zoom: (cb: CallBack) => {
this.map.on('zoom', cb)
},
move: (cb: CallBack) => {
this.map.on('move', cb)
},
blur: (cb: CallBack) => {
this.map.on('blur', cb)
},
focus: (cb: CallBack) => {
this.map.on('focus', cb)
},
drag: (cb: CallBack) => {
this.map.on('drag', cb)
},
resize: (cb: CallBack) => {
this.map.on('resize', cb)
},
click: (cb: ClickCallBack) => {
this._clickCb = cb
this.map.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,
}
cb(arg)
})
},
}
this._listeners = Object.assign(this._listeners, _listeners)
}
/** 设置控制器 */
private _setControls() {
const _controls: Partial<Controls> = {
compass: (options?: ControlOptions) => {
this.map.addControl(new aimap.CompassControl(), options?.position)
},
zoom: (options?: ControlOptions) => {
this.map.addControl(
new aimap.NavigationControl({
showZoom: options?.show,
showCompass: false,
visualizePitch: false,
}),
options?.position,
)
},
scale: (options?: ControlOptions) => {
this.map.addControl(
new aimap.ScaleControl({
maxWidth: options?.maxWidth || 80,
unit: options?.unit || 'metric',
}),
options?.position,
)
},
}
this._controls = Object.assign(this._controls, _controls)
}
/** 设置覆盖物 */
private _setLayers() {
const makeLayer = (layer: any) => {
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
}
const _layers: Partial<Layers> = {
point: (data: LayerOption) =>
makeLayer(new aimap.MassMarkerLayer(toPoints(this.map, data))),
line: (data: LayerOption) =>
makeLayer(new aimap.LineString(toLines(this.map, data))),
polygon: (data: LayerOption) =>
makeLayer(new aimap.Polygon(toPolygons(this.map, data))),
}
this._layers = Object.assign(this._layers, _layers)
}
zoomIn(options: ZoomOptions) {
this.map.zoomIn(options)
}
zoomOut(options: ZoomOptions) {
this.map.zoomOut(options)
}
zoomTo(level: number, options: ZoomOptions) {
this.map.zoomTo(level, options)
}
focus(location: Location, options?: FocusOptions) {
this.map.flyTo({
center: location,
...options,
})
}
remove(layer: any) {
layer && layer.remove()
}
addBoundary() {
console.error('此地图不存在 addBoundary 方法')
return { remove: () => null }
}
}
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,
],
},
}
}
/** 转化面状覆盖物 */
export function toPolygons(map: unknown, options: LayerOption) {
const {
data,
lineWidth = 3,
color = 'blue',
fillColor = 'rgba(135,206,235,0.5)',
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,
'fill-color': fillColor,
'line-join': lineJoin,
'text-field': `{${labelKey}}`,
'text-color': labelOptions?.color,
// 偏移相比测绘院地图大概小了10倍,且竖直偏移相反
'text-offset': [
horizontal ? horizontal / 10 : 0,
vertical ? vertical / -10 : 0,
],
},
}
}
import { MapConfig, EventListener } from './types' import { AIMapConfig, MapConfig, SMapConfig } from './types'
import Map from './map' import type MapType from './my-map'
import S_Map from './s-map' import S_Map from './s-map'
import A_Map from './a-map' import AI_Map from './ai-map'
export type MapType = Omit<Map, keyof EventListener> const whichMap = {
SMap: {
export async function createMap(config: MapConfig): Promise<MapType> { /**
await _injectSource(config) * 使用配置初始化地图
return _whichMap(config) * @param config 地图配置
*/
with: (config: MapConfig<SMapConfig>) => new S_Map(config),
},
AIMap: {
/**
* 使用配置初始化地图
* @param config 地图配置
*/
with: (config: MapConfig<AIMapConfig>) => new AI_Map(config),
},
} }
function _injectSource(config: MapConfig): Promise<unknown[]> { export type MyMap = MapType
if (!config.sources || config.sources.length === 0) { export namespace MyMap {
return Promise.resolve([true]) /**
* 创建地图
* @param key 地图关键字:
*
* 'SMap': 测绘院地图
*
* 'AIMap': 维智地图
*
*/
export function useMap<K extends keyof typeof whichMap>(key: K) {
return whichMap[key]
} }
const promises = config.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)
} }
function _whichMap(config: MapConfig): Map { // function _injectSource(sources: any[]): Promise<unknown[]> {
const { type } = config // const promises = sources.map((source: string, index: number) => {
switch (type) { // return new Promise((resolve) => {
case 'SMap': // const id = `_my_map_source${index}`
return new S_Map(config) // if (document.getElementById(id)) return resolve(true)
case 'AMap':
return new A_Map(config) // const mapSource = document.createElement('script')
default: // mapSource.type = 'text/javascript'
if (type) { // mapSource.src = source
throw new Error(`不存在${type}类型的地图!`) // mapSource.setAttribute('id', id)
} else { // document.body.appendChild(mapSource)
// eslint-disable-next-line // mapSource.onload = () => resolve(true)
throw new Error('初始化地图需要配置\'type\'字段!') // })
} // })
} // return Promise.all(promises)
} // }
declare const SMap: {
Map: any
MapEvent: any
Size: any
Icon: any
Label: any
Marker: any
Polyline: any
Polygon: 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: new (view: any) => {
add: (options: any) => void
remove: () => void
}
}
declare const aimap: {
Map: any
accessToken: string
baseApiUrl: string
NavigationControl: any
CompassControl: any
ScaleControl: any
MassMarkerLayer: any
LineString: any
Polygon: any
}
import {
CallBack,
EventListener,
BoundaryOption,
MarkerOption,
EventName,
} from './types'
export default abstract class Map implements EventListener {
protected map
constructor(map: any) {
this.map = map
}
get instance(): any {
return this.map
}
on<T extends keyof EventListener>(name: EventName, cb: CallBack): this {
const eventName = `on${name.slice(0, 1).toUpperCase()}${name
.slice(1)
.toLowerCase()}` as T
if (!this[eventName]) throw new Error(`地图不存在'${name}'事件`)
this[eventName](cb)
return this
}
abstract onLoad(cb: CallBack): void
abstract onZoom(cb: CallBack): void
abstract onMove(cb: CallBack): void
abstract onBlur(cb: CallBack): void
abstract onFocus(cb: CallBack): void
abstract onDrag(cb: CallBack): void
abstract onResize(cb: CallBack): void
abstract onClick(cb: CallBack): void
abstract onDblclick(cb: CallBack): void
abstract onMousewheel(cb: CallBack): void
abstract zoomIn(): void
abstract zoomOut(): void
abstract hideCommunity(): void
abstract showCommunity(): void
abstract filterCommunity(ids: unknown[], key: string): void
abstract focus(location: number[], zoom?: number): void
abstract addBoundary(option: BoundaryOption): unknown
abstract addMarkers(option: MarkerOption): unknown
abstract remove(markers: unknown): void
}
import {
CallBack,
ControlOptions,
Controls,
Listeners,
ZoomOptions,
FocusOptions,
Location,
Layers,
LayerOption,
BoundaryOption,
} from './types'
const defaultListeners = {
load: () => console.error('on:此地图不存在 load 监听事件!'),
zoom: () => console.error('on:此地图不存在 zoom 监听事件!'),
move: () => console.error('on:此地图不存在 move 监听事件!'),
blur: () => console.error('on:此地图不存在 blur 监听事件!'),
focus: () => console.error('on:此地图不存在 focus 监听事件!'),
drag: () => console.error('on:此地图不存在 drag 监听事件!'),
resize: () => console.error('on:此地图不存在 resize 监听事件!'),
click: () => console.error('on:此地图不存在 click 监听事件!'),
dblclick: () => console.error('on:此地图不存在 dblclick 监听事件!'),
mousewheel: () => console.error('on:此地图不存在 mousewheel 监听事件!'),
}
const defaultControls = {
home: () => console.error('set:此地图不存在 home 控件!'),
zoom: () => console.error('set:此地图不存在 home 控件!'),
compass: () => console.error('set:此地图不存在 home 控件!'),
scale: () => console.error('set:此地图不存在 scale 控件!'),
fullScreen: () => console.error('set:此地图不存在 fullScreen 控件!'),
layerList: () => console.error('set:此地图不存在 layerList 控件!'),
measureLine: () => console.error('set:此地图不存在 measureLine 控件!'),
measureArea: () => console.error('set:此地图不存在 measureArea 控件!'),
basemapToggle: () => console.error('set:此地图不存在 basemapToggle 控件!'),
underguroundSwitch: () =>
console.error('set:此地图不存在 underguroundSwitch 控件!'),
bMapGallery: () => console.error('set:此地图不存在 bMapGallery 控件!'),
bMapGalleryexpand: () =>
console.error('set:此地图不存在 bMapGalleryexpand 控件!'),
}
const defaultLayers = {
point: () => console.error('add:此地图不存在 point 覆盖物!'),
line: () => console.error('add:此地图不存在 line 覆盖物!'),
polygon: () => console.error('add:此地图不存在 polygon 覆盖物!'),
boundary: () => console.error('add:此地图不存在 boundary 覆盖物!'),
}
export default abstract class MyMap {
protected map
protected _listeners: Listeners = defaultListeners
protected _controls: Controls = defaultControls
protected _layers: Layers = defaultLayers
constructor(instance: any) {
this.map = instance
}
/**
* 原始地图实例
* (主要适用于调用原始地图的方法、功能)
*/
get instance(): any {
return this.map
}
/**
* 监听事件
* @param name 事件名称
* @param cb 回调函数
*/
on<K extends keyof Listeners>(name: K, cb: CallBack) {
this._listeners[name](cb)
return this
}
/**
* 添加控件
* @param name 控件名称
* @param options 控件参数:
*/
set<K extends keyof Controls>(name: K, options: ControlOptions = {}) {
if (options.show === undefined) options.show = true
if (options.position === undefined) options.position = 'top-right'
this._controls[name](options)
return this
}
/**
* 添加覆盖物
* @param type 覆盖物类型
* @param data 覆盖物数据
*/
add<K extends keyof Layers>(type: K, data: LayerOption) {
return this._layers[type](data)
}
/**
* zoom in
* @param options 参数
*/
abstract zoomIn(options?: ZoomOptions): void
/**
* zoom out
* @param options 参数
*/
abstract zoomOut(options?: ZoomOptions): void
/**
* zoom to
* @param level 等级
* @param options 参数
*/
abstract zoomTo(level: number, options?: ZoomOptions): void
/**
* 聚焦
* @param location 坐标
* @param options 参数
*/
abstract focus(location: Location, options?: FocusOptions): void
/**
* 移除覆盖物
* @param layer 覆盖物
*/
abstract remove(layer: unknown): void
/**
* 添加边界
* @param option 配置项
*/
abstract addBoundary(option: BoundaryOption): { remove: () => void }
}
import { MapConfig, CallBack, BoundaryOption, MarkerOption } from './types'
import Map from './map'
declare const SMap: {
Map: any
Network: any
MapEvent: any
Size: any
Icon: any
Label: any
Marker: any
}
declare const Plugins: {
MaskBoundary: any
}
export default class S_Map extends Map {
constructor(config: MapConfig) {
new SMap.Network().setNet(config.options.netType || 'internet')
super(new SMap.Map(config.el, config.options))
}
onLoad(cb: CallBack): void {
this.map.on(SMap.MapEvent.maploaded, cb)
}
onZoom(cb: CallBack): void {
this.map.on(SMap.MapEvent.zoomchanged, cb)
}
onMove(cb: CallBack): void {
this.map.on(SMap.MapEvent.centerchanged, cb)
}
private event(event: unknown, cb: CallBack) {
this.map.on(event, (view: any, eventParamter: unknown) => {
view.hitTest(eventParamter).then((res: unknown) => {
cb(res, eventParamter)
})
})
}
onBlur(cb: CallBack): void {
this.event(SMap.MapEvent.blur, cb)
}
onFocus(cb: CallBack): void {
this.event(SMap.MapEvent.focus, cb)
}
onDrag(cb: CallBack): void {
this.event(SMap.MapEvent.drag, cb)
}
onResize(cb: CallBack): void {
this.event(SMap.MapEvent.resize, cb)
}
onClick(cb: CallBack): void {
this.event(SMap.MapEvent.click, cb)
}
onDblclick(cb: CallBack): void {
this.event(SMap.MapEvent.doubleclick, cb)
}
onMousewheel(cb: CallBack): void {
this.event(SMap.MapEvent.mousewheel, cb)
}
zoomIn(): void {
this.map.zoomIn()
}
zoomOut(): void {
this.map.zoomOut()
}
hideCommunity(): void {
this.map.hideXQ_Poly()
this.map.hideMPZ()
this.map.hideXQ_Point()
}
showCommunity(): void {
this.map.showXQ_Poly()
this.map.showMPZ()
this.map.showXQ_Point()
}
filterCommunity(ids: unknown[], key = 'sect_id'): void {
if (ids.length === 0) return
const valid = ids.map((val: unknown) => {
return `${key} = '${val}'`
})
this.map.setFilter('wg_gis_xq_point', valid.join(' or '))
this.map.setFilter('wg_gis_mpz', valid.join(' or '))
this.map.setFilter('wg_gis_xq_poly', valid.join(' or '))
}
focus(location: number[], zoom = this.map.getZoom()): void {
this.map.setZoomAndCenter(zoom, location)
}
addBoundary({
name,
type,
weight = 10,
count = 10,
color = 'rgba(51,145,255,.6)',
maskColor = [0, 17, 33, 0.9],
}: BoundaryOption): unknown {
if (!name || !type) {
throw new Error('SMap的addBoundary方法需要name和type参数!')
return
}
const boundary = {
boundaryType: type,
boundaryDefinition: `name like '%${name}%'`,
boundarydistance: weight,
bounarycount: count,
boundaryColor: color,
maskColor: maskColor,
}
const Boundary = new Plugins.MaskBoundary(this.map.view)
Boundary.add(boundary)
return Boundary
}
private transMarkerData(option: MarkerOption): unknown[] {
const { data = [], size, icon, key, labelKey, color } = option
return data.map((item: any) => {
let sizeProp = Array.isArray(size)
? new SMap.Size(size[0], size[1])
: new SMap.Size(size, size)
if (item.size) {
sizeProp = Array.isArray(item.size)
? new SMap.Size(item.size[0], item.size[1])
: new SMap.Size(item.size, item.size)
}
const result = {
icon: new SMap.Icon({
size: sizeProp,
image: item.icon || icon,
}),
attributes: { key, ...item },
position: [
item.X || item.x || item.gpsx || item.lon,
item.Y || item.y || item.gpsy || item.lat,
item.Z || item.z || item.gpsz || 0,
],
label: new SMap.Label({
text: labelKey ? item[labelKey] + '' : '',
size,
color,
}),
}
return new SMap.Marker(result)
})
}
addMarkers(option: MarkerOption): unknown {
const markers = this.transMarkerData(option)
this.map.add(markers)
return markers
}
remove(markers: unknown): void {
this.map.remove(markers)
}
}
import MyMap from '../my-map'
import {
CallBack,
MapConfig,
Listeners,
ControlOptions,
Location,
FocusOptions,
Controls,
SMapConfig,
Layers,
LayerOption,
ClickCallBack,
BoundaryOption,
} from '../types'
import { toLines, toPoints, toPolygons } from './util'
/** 测绘院地图 */
export default class S_Map extends MyMap {
constructor(config: MapConfig<SMapConfig>) {
if (!config.netType) {
throw new Error('SMap需要设置netType参数!')
}
new SMap.Network().setNet(config.netType)
const instance = new SMap.Map(config.el, {
appKey: config.appKey,
viewMode: config.mode,
center: config.center,
zoom: config.zoom,
zooms: config.zooms,
pitch: config.pitch,
mapStyle: config.style,
showBuildingBlock: config.showBuildingBlock,
rotateEnable: config.rotateEnable,
})
super(instance)
this._setListeners()
this._setControls()
this._setLayers()
this.on('load', this._clearFooter)
}
/** 清除地图自带的脚注 */
private _clearFooter() {
const footer = document.querySelector(
'.esri-ui-manual-container>.esri-component',
)
footer && ((footer as HTMLElement).style.display = 'none')
}
/** 设置监听事件 */
private _setListeners() {
const _listeners: Partial<Listeners> = {
load: (cb: CallBack) => {
this.map.on(SMap.MapEvent.maploaded, cb)
},
zoom: (cb: CallBack) => {
this.map.on(SMap.MapEvent.zoomchanged, cb)
},
move: (cb: CallBack) => {
this.map.on(SMap.MapEvent.centerchanged, cb)
},
blur: (cb: CallBack) => {
this.map.on(SMap.MapEvent.blur, cb)
},
focus: (cb: CallBack) => {
this.map.on(SMap.MapEvent.focus, cb)
},
drag: (cb: CallBack) => {
this._addEvent(SMap.MapEvent.drag, cb)
},
resize: (cb: CallBack) => {
this.map.on(SMap.MapEvent.resize, cb)
},
click: (cb: CallBack) => {
this._addEvent(SMap.MapEvent.click, cb)
},
dblclick: (cb: CallBack) => {
this._addEvent(SMap.MapEvent.doubleclick, cb)
},
mousewheel: (cb: CallBack) => {
this._addEvent(SMap.MapEvent.mousewheel, cb)
},
}
this._listeners = Object.assign(this._listeners, _listeners)
}
/** 特殊的可能会带自定义数据的事件 */
private _addEvent(event: unknown, cb: ClickCallBack) {
this.map.on(event, (view: any, e: any) => {
const arg = {
type: e.type,
center: [e.mapPoint?.longitude, e.mapPoint?.latitude],
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?.[0]?.graphic?.attributes || null)
})
})
}
/** 设置控制器 */
private _setControls() {
const makeControl = (constructorFn: any, options?: ControlOptions) => {
this.map.addControl(
new constructorFn({
visible: options?.show,
position: options?.position,
}),
)
}
const _controls: Partial<Controls> = {
home: (options?: ControlOptions) => {
makeControl(SMap.Home, options)
},
compass: (options?: ControlOptions) => {
makeControl(SMap.Compass, options)
},
zoom: (options?: ControlOptions) => {
makeControl(SMap.Zoom, options)
},
fullScreen: (options?: ControlOptions) => {
makeControl(SMap.Fullscreen, options)
},
layerList: (options?: ControlOptions) => {
makeControl(SMap.LayerListControl, options)
},
measureLine: (options?: ControlOptions) => {
makeControl(SMap.MeasureLine, options)
},
measureArea: (options?: ControlOptions) => {
makeControl(SMap.MeasureArea, options)
},
basemapToggle: (options?: ControlOptions) => {
makeControl(SMap.BasemapToggle, options)
},
underguroundSwitch: (options?: ControlOptions) => {
makeControl(SMap.UndergroundSwitch, options)
},
bMapGallery: (options?: ControlOptions) => {
makeControl(SMap.BMapGallery, options)
},
bMapGalleryexpand: (options?: ControlOptions) => {
makeControl(SMap.BMapGalleryExpand, options)
},
}
this._controls = Object.assign(this._controls, _controls)
}
/** 设置覆盖物 */
private _setLayers() {
const makeLayer = (group: unknown[]) => {
const layer = new SMap.OverlayGroup(group, {})
this.map.add(layer)
return layer
}
const _layers: Partial<Layers> = {
point: (data: LayerOption) => makeLayer(toPoints(data)),
line: (data: LayerOption) => makeLayer(toLines(data)),
polygon: (data: LayerOption) => makeLayer(toPolygons(data)),
}
this._layers = Object.assign(this._layers, _layers)
}
zoomIn() {
this.map.zoomIn()
}
zoomOut() {
this.map.zoomOut()
}
zoomTo(level: number) {
this.map.setZoom(level)
}
focus(location: Location, options?: FocusOptions) {
const level = options?.zoom || this.map.getZoom()
this.map.setZoomAndCenter(level, location)
}
remove(layer: unknown) {
layer && this.map.remove(layer)
}
/** 添加边界 */
addBoundary({
name = '',
type = 'jd_boundary',
weight = 10,
count = 10,
color = 'rgba(51,145,255,.6)',
maskColor = [0, 17, 33, 0.9],
}: BoundaryOption) {
const boundary = new Plugins.MaskBoundary(this.map.view)
boundary.add({
boundaryType: type,
boundaryDefinition: `name like '%${name}%'`,
boundarydistance: weight,
bounarycount: count,
boundaryColor: color,
maskColor: maskColor,
})
return boundary
}
}
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)]
}
}
/** 转化面状覆盖物 */
export function toPolygons(options: LayerOption) {
const {
data,
color = 'blue',
fillColor = 'rgba(135,206,235,0.5)',
labelKey,
labelOptions,
lineCap = 'square',
lineStyle = 'solid',
lineJoin = 'round',
lineWidth = 3,
} = options
const transData = (item: PointsData) => {
const result: any = {
paths: item.path?.map(([x, y]) => new SMap.LngLat(x, y)),
attributes: { ...item },
cap: lineCap,
strokeColor: color,
fillColor,
strokeWeight: lineWidth,
style: lineStyle,
lineJoin: lineJoin,
}
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.Polygon(result)
}
if (Array.isArray(data)) {
return data.map(transData)
} else {
return [transData(data)]
}
}
export interface EventListener { /**
onLoad: (cb: CallBack) => void * 地图配置
onZoom: (cb: CallBack) => void */
onMove: (cb: CallBack) => void export type MapConfig<T> = T & {
onBlur: (cb: CallBack) => void /** 地图容器(需要有宽高) */
onFocus: (cb: CallBack) => void el: string
onDrag: (cb: CallBack) => void /**
onResize: (cb: CallBack) => void * 在SMap中作为appKey使用
onClick: (cb: CallBack) => void * 在AIMap中作为accessToken使用
onDblclick: (cb: CallBack) => void */
onMousewheel: (cb: CallBack) => void appKey: string
} & Partial<{
/** 地图模式 */
mode: '2D' | '3D'
/** 地图初始中心点位 */
center: Location
/** 地图初始zoom等级 */
zoom: number
/** 地图zoom允许范围 */
zooms: [number, number]
/** 地图初始旋转角度 */
bearing: number
/** 地图初始仰角(3D用) */
pitch: number
/** 地图仰角允许范围 */
pitchs: [number, number]
/** 地图样式 */
style: string
showBuildingBlock: boolean
rotateEnable: boolean
family: string
}>
export type SMapConfig = {
/**
* SMap 地图专用
* @param internet 表示互联网2D
* @param affairs 表示政务网2D
* @param local3D 表示局域网3D
* @param affairs3D 表示政务网3D
* @param njdl 表示南京东路政务网3D
*/
netType: 'internet' | 'affairs' | 'local3D' | 'affairs3D' | 'njdl'
}
export type AIMapConfig = {
baseApiUrl: string
} }
export type EventName = export type Location = [number, number] | [number, number, number]
| 'load'
| 'zoom'
| 'move'
| 'blur'
| 'focus'
| 'drag'
| 'resize'
| 'click'
| 'dblclick'
| 'mousewheel'
export interface MapConfig { /**
el: string * 坐标系类型
type: 'SMap' | 'AMap' | 'BMap' * @param gcj02 高德坐标系
options: MapOptions * @param wgs84 gps坐标系
sources?: string[] * @param bd09 百度坐标系
* @param cgcs2000 城建坐标系
*/
export type LocationType = 'gcj02' | 'wgs84' | 'bd09' | 'cgcs2000'
/**
* 监听回调函数
*/
export type CallBack = (arg: any, oth?: any) => unknown
/** 经过封装的返回统一参数的点击回调 */
export type ClickCallBack = (
arg: {
/** 事件类型 */
type: string
/** 地图初始中心点位 */
center: number[]
/** 鼠标事件 */
event: PointerEvent
/** 触发时鼠标x位置 */
clientX: number
/** 触发时鼠标y位置 */
clientY: number
/** 鼠标点击x坐标 */
x?: number
/** 鼠标点击y坐标 */
y?: number
/** 地图触发事件的原始数据(即未经封装前的数据) */
originData: any
},
oth?: any,
) => unknown
/**
* 监听事件
*/
export interface Listeners {
/** 加载完成触发 */
load: (cb: CallBack) => unknown
/** zoom变化触发 */
zoom: (cb: CallBack) => unknown
/** 地图移动 */
move: (cb: CallBack) => unknown
/** 失焦触发 */
blur: (cb: CallBack) => unknown
/** 聚焦触发 */
focus: (cb: CallBack) => unknown
/** 拖动触发 */
drag: (cb: CallBack) => unknown
/** 视图大小变化触发 */
resize: (cb: CallBack) => unknown
/** 点击触发 */
click: (cb: ClickCallBack) => unknown
/** 双击触发 */
dblclick: (cb: CallBack) => unknown
/** 滚轮触发 */
mousewheel: (cb: CallBack) => unknown
}
type Position = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
/**
* 控制器选项
*/
export interface ControlOptions {
show?: boolean
/** 控件位置 */
position?: Position
/** ScaleControl控件的最大长度,以像素为单位 */
maxWidth?: number
/** ScaleControl控件的距离单位 */
unit?: 'imperial' | 'metric' | 'nautical'
}
/**
* 控制器列表
*/
export interface Controls {
home: (options?: ControlOptions) => void
compass: (options?: ControlOptions) => void
zoom: (options?: ControlOptions) => void
scale: (options?: ControlOptions) => void
fullScreen: (options?: ControlOptions) => void
layerList: (options?: ControlOptions) => void
measureLine: (options?: ControlOptions) => void
measureArea: (options?: ControlOptions) => void
basemapToggle: (options?: ControlOptions) => void
underguroundSwitch: (options?: ControlOptions) => void
bMapGallery: (options?: ControlOptions) => void
bMapGalleryexpand: (options?: ControlOptions) => void
}
/**
* zoom配置参数(维智地图用)
*/
export interface ZoomOptions {
/** 如果 false ,则没有动画效果(默认true) */
animate?: boolean
/** 动态转换的持续时间,按毫秒计算(默认3000) */
duration?: number
/** 该函数持续的时间在 0~1 之间, 返回一个表示状态的数字,初始状态为 0,最终状态为 1 */
easing?: (t?: number) => number | void
/** 动态转换结束后,目标中心与实际地图容器中心间的偏差,单位为像素 */
offset?: [number, number]
} }
export interface MapOptions { /**
viewMode?: '2D' | '3D' * focus配置参数(测绘院地图只有zoom有用)
center?: number[] */
zooms?: number[] export interface FocusOptions {
/**地图缩放等级(默认当前等级) */
zoom?: number zoom?: number
/** 地图倾斜角度(默认当前角度) */
pitch?: number pitch?: number
rotation?: number /** 地图旋转角度(默认当前角度) */
mapStyle?: string bearing?: number
showBuildingBlock?: boolean /** 图层距离容器四周距离(单位像素) */
resizeEnable?: boolean padding?: { top?: number; bottom?: number; left?: number; right?: number }
rotateEnable?: boolean /** 动画速度(默认1.2) */
pitchEnable?: boolean speed?: number
showLabel?: boolean /** 默认1.42 */
buildingAnimation?: boolean // 楼块出现是否带动画 curve?: number
expandZoomRange?: boolean /** 整个fly动画持续毫秒时间(默认3000) */
showIndoorMap?: boolean maxDuration?: number
features?: string[]
netType?: string
} }
export type CallBack = (arg: unknown, oth?: unknown) => void /**
* 覆盖物列表
*/
export interface Layers {
point: (data: LayerOption) => unknown
line: (data: LayerOption) => unknown
polygon: (data: LayerOption) => unknown
}
// export type CallBackDic = { [key: string]: CallBack } /** 覆盖物点位数据 */
export interface PointsData {
id?: string
x?: number
y?: number
z?: number
X?: number
Y?: number
Z?: number
gpsx?: number
gpsy?: number
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
labelKey?: string
labelOptions?: {
size?: number
/** [水平偏移量,垂直偏移量] */
offset?: [number, number] | [number, number, number]
color?: string
}
color?: string
fillColor?: string
lineCap?: string
lineStyle?: string
lineJoin?: 'bevel' | 'round' | 'miter'
lineWidth?: number
}
/** 边界选项 */
export interface BoundaryOption { export interface BoundaryOption {
name?: string /** 根据type模糊匹配名称 */
name: string
/**
* 边界类型
*
* 'jd_boundary' : 街道
*
* 'jwh_boundary' : 南东工作站
*/
type?: string type?: string
weight?: number weight?: number
count?: number count?: number
color?: string color?: string
maskColor?: number[] maskColor?: number[]
} }
export interface MarkerOption {
data: unknown[]
key?: string
labelKey?: string
icon?: string
size?: number | number[]
color?: string
}
<template> <template>
<div ref="mapRef" class="map" /> <div id="container" />
<div class="btn">
<button @click="zoom('in')">zoom in</button>
<button @click="zoom('out')">zoom out</button>
</div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, nextTick, onMounted } from 'vue' import icon1 from '@/assets/images/search.png'
import { createMap, MapType } from '@/components/my-map' import { MyMap } from '@/components/my-map'
import { nextTick, onMounted } from 'vue'
let map: MyMap
let pointsLayer: any
let linesLayer: any
let polygonLayer: any
let boundary: any
const mapRef = ref<any>(null)
let map: MapType
onMounted(async () => { onMounted(async () => {
await nextTick() await nextTick()
map = await createMap({
el: mapRef.value, map = MyMap.useMap('SMap').with({
type: 'SMap', el: 'container',
options: { center: [0, 0],
viewMode: '2D', zoom: 5,
center: [1019.614669, 54.167243], style: 'smap://styles/dark',
zooms: [7, 12], appKey: 'DTZ49ACE32PBN73GXPF085',
zoom: 8, netType: 'internet',
pitch: 45, })
mapStyle: 'smap://styles/dark',
netType: 'internet', map
.on('load', () => console.log('load'))
.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))
.on('focus', (e) => console.log('focus: ', e))
.on('drag', (e) => console.log('drag: ', e))
.on('resize', (e) => console.log('resize: ', e))
.on('dblclick', (e) => console.log('dblclick: ', e))
.on('mousewheel', (e) => console.log('mousewheel: ', e))
})
function zoomIn() {
map.zoomIn()
}
function zoomOut() {
map.zoomOut()
}
function zoomTo() {
map.zoomTo(20)
}
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',
}, },
sources: ['/SMap.min.js', '/Plugins.min.js'],
}) })
map.on('load', () => { }
map.hideCommunity() function addLines() {
map linesLayer = map.add('line', {
.on('click', (a, b) => { data: {
console.log('click', a, b) path: [
}) [0, 0],
.on('dblclick', (a, b) => { [121.59751247938203, 29.835174764721145],
console.log('dblclick', a, b) ],
}) text: 'test message',
.on('zoom', (a, b) => { },
console.log('zoom', a, b) labelKey: 'text',
}) })
.on('focus', (a, b) => { }
console.log('focus', a, b) function addPolygon() {
}) polygonLayer = map.add('polygon', {
.on('move', (a, b) => { data: {
console.log('move', a, b) path: [
}) [0, 0],
.on('blur', (a, b) => { [121.59751247938203, 29.835174764721145],
console.log('blur', a, b) [21.59751247938203, 0.835174764721145],
}) [0, 0],
.on('drag', (a, b) => { ],
console.log('drag', a, b) text: 'test message',
}) },
.on('resize', (a, b) => {
console.log('resize', a, b)
})
.on('mousewheel', (a, b) => {
console.log('mousewheel', a, b)
})
}) })
}) }
const zoom = (type: string) => {
if (type === 'in') { function removeLayers() {
map.zoomIn() map.remove(pointsLayer)
map.showCommunity() map.remove(linesLayer)
} else { map.remove(polygonLayer)
map.zoomOut() boundary.remove()
}
} }
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.map #container
position fixed
width 100vw width 100vw
height 100vh height 100vh
.btn position fixed
position absolute top 0
right 20px left 0
top 20px
</style> </style>
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
columns="1fr 1.5fr 1fr" columns="1fr 1.5fr 1fr"
:rows="`${layout.rows}`" :rows="`${layout.rows}`"
> >
<Map />
<div <div
v-for="(_, index) in new Array(layout.boxNum)" v-for="(_, index) in new Array(layout.boxNum)"
:key="index" :key="index"
...@@ -31,7 +32,7 @@ ...@@ -31,7 +32,7 @@
</div> </div>
</m-modal> </m-modal>
</div> </div>
<MapBtns :isDefaultScreen="isDefaultScreen" @touch="handleMapBtnsEvents" /> <MapBtns :is-default-screen="isDefaultScreen" @touch="handleMapBtnsEvents" />
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
...@@ -41,6 +42,7 @@ import { onMounted, ref } from 'vue' ...@@ -41,6 +42,7 @@ import { onMounted, ref } from 'vue'
import { ajax, api } from '@/ajax' import { ajax, api } from '@/ajax'
import { NSpace, NButton } from 'naive-ui' import { NSpace, NButton } from 'naive-ui'
import MapBtns from './components/map-btns.vue' import MapBtns from './components/map-btns.vue'
import Map from './components/map.vue'
const { layout } = useLayout() const { layout } = useLayout()
const { components, componentList } = useComponent() const { components, componentList } = useComponent()
......
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