什么是GeoScene Maps
GeoScene Maps是一套功能强大的Web地图开发平台,它基于现代Web技术构建,为开发者提供了丰富的地图服务和开发工具。与其他地图API相比,GeoScene Maps具有以下特点:
核心优势
- 全面的地图服务:支持2D/3D地图、多种底图类型
- 高性能渲染:基于WebGL的高效渲染引擎
- 丰富的API:完整的地图操作、空间分析功能
- 跨平台支持:支持桌面端和移动端
- 灵活的样式:可自定义地图样式和符号
适用场景
- 位置服务应用
- 物流追踪系统
- 智慧城市平台
- 地理信息系统(GIS)
- 实时监控系统
环境准备与安装
1. 前置要求
在开始之前,确保您的开发环境满足以下要求:
# Node.js版本要求
Node.js >= 14.0.0
npm >= 6.0.0
# 或者使用yarn
yarn >= 1.22.0
2. 创建Vue项目
# 使用Vue CLI创建项目
npm install -g @vue/cli
vue create geoscene-map-demo
# 或使用Vite创建项目(推荐)
npm create vue@latest geoscene-map-demo
cd geoscene-map-demo
npm install
3. 安装GeoScene Maps SDK
# 安装GeoScene Maps核心包
npm install @geoscene/core
# 如果需要额外的功能模块
npm install @geoscene/map-components
npm install @geoscene/calcite-components
创建第一个地图
1. 基础地图组件
首先,让我们创建一个基础的地图组件:
<!-- src/components/MapContainer.vue -->
<template>
<div class="map-container">
<div
ref="mapDiv"
class="map-view"
id="map-view"
></div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import Map from '@geoscene/core/Map.js'
import MapView from '@geoscene/core/views/MapView.js'
import TileLayer from '@geoscene/core/layers/TileLayer.js'
// 模板引用
const mapDiv = ref(null)
// 地图实例
let map = null
let view = null
// 初始化地图
const initializeMap = async () => {
try {
// 创建地图实例
map = new Map({
basemap: 'streets-navigation-vector' // 使用内置底图
})
// 创建地图视图
view = new MapView({
container: mapDiv.value,
map: map,
center: [116.397, 39.909], // 北京天安门坐标
zoom: 13
})
// 等待视图加载完成
await view.when()
console.log('地图初始化完成')
} catch (error) {
console.error('地图初始化失败:', error)
}
}
// 组件挂载时初始化地图
onMounted(() => {
initializeMap()
})
// 组件卸载时清理资源
onUnmounted(() => {
if (view) {
view.destroy()
view = null
}
map = null
})
// 暴露地图实例供父组件使用
defineExpose({
getMap: () => map,
getView: () => view
})
</script>
<style scoped>
.map-container {
width: 100%;
height: 100%;
position: relative;
}
.map-view {
width: 100%;
height: 100%;
}
</style>
2. 使用自定义底图
如果需要使用天地图等国内地图服务
// src/utils/mapConfig.js
export const TIANDITU_CONFIG = {
key: '您的天地图API密钥', // 需要到天地图官网申请
baseUrl: 'https://t{subDomain}.tianditu.gov.cn'
}
export const MAP_TYPES = {
SATELLITE: 'satellite', // 卫星图
VECTOR: 'vector', // 矢量图
TERRAIN: 'terrain' // 地形图
}
// 创建天地图底图的函数
import WebTileLayer from '@geoscene/core/layers/WebTileLayer.js'
import Basemap from '@geoscene/core/Basemap.js'
import { TIANDITU_CONFIG } from '@/utils/mapConfig.js'
const createTiandituBasemap = (mapType = 'vector') => {
let layerType = ''
let annotationType = ''
switch (mapType) {
case 'satellite':
layerType = 'img_w'
annotationType = 'cia_w'
break
case 'terrain':
layerType = 'ter_w'
annotationType = 'cta_w'
break
default: // vector
layerType = 'vec_w'
annotationType = 'cva_w'
}
return new Basemap({
baseLayers: [
// 底图层
new WebTileLayer({
urlTemplate: `${TIANDITU_CONFIG.baseUrl}/${layerType}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${layerType.split('_')[0]}&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=${TIANDITU_CONFIG.key}`,
subDomains: ['0', '1', '2', '3'],
copyright: '© 天地图'
}),
// 标注层
new WebTileLayer({
urlTemplate: `${TIANDITU_CONFIG.baseUrl}/${annotationType}/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=${annotationType.split('_')[0]}&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&tk=${TIANDITU_CONFIG.key}`,
subDomains: ['0', '1', '2', '3'],
copyright: '© 天地图'
})
]
})
}
地图基础操作
1. 地图导航控制
// 添加地图导航控件
import Home from '@geoscene/core/widgets/Home.js'
import Zoom from '@geoscene/core/widgets/Zoom.js'
import Compass from '@geoscene/core/widgets/Compass.js'
const addMapControls = (view) => {
// 添加缩放控件
const zoomWidget = new Zoom({
view: view
})
view.ui.add(zoomWidget, 'top-left')
// 添加指南针控件
const compassWidget = new Compass({
view: view
})
view.ui.add(compassWidget, 'top-left')
// 添加主页按钮
const homeWidget = new Home({
view: view
})
view.ui.add(homeWidget, 'top-left')
}
2. 地图视图操作
// 地图操作工具函数
export const mapOperations = {
// 跳转到指定位置
goTo: async (view, target, options = {}) => {
try {
await view.goTo(target, {
duration: options.duration || 1000,
easing: options.easing || 'ease-in-out'
})
} catch (error) {
console.error('地图跳转失败:', error)
}
},
// 设置地图中心点
setCenter: (view, longitude, latitude, zoom = null) => {
view.center = [longitude, latitude]
if (zoom !== null) {
view.zoom = zoom
}
},
// 获取当前地图范围
getExtent: (view) => {
return view.extent
},
// 设置地图范围
setExtent: async (view, extent) => {
try {
await view.goTo(extent)
} catch (error) {
console.error('设置地图范围失败:', error)
}
}
}
3. 地图事件处理
// 地图事件监听
const setupMapEvents = (view) => {
// 点击事件
view.on('click', (event) => {
console.log('地图被点击:', event.mapPoint)
const { longitude, latitude } = event.mapPoint
console.log(`坐标: ${longitude}, ${latitude}`)
})
// 双击事件
view.on('double-click', (event) => {
console.log('地图被双击:', event.mapPoint)
// 阻止默认的缩放行为
event.stopPropagation()
})
// 鼠标移动事件
view.on('pointer-move', (event) => {
// 获取鼠标位置的地理坐标
const point = view.toMap(event)
if (point) {
// 可以在这里更新坐标显示
updateCoordinateDisplay(point.longitude, point.latitude)
}
})
// 地图范围变化事件
view.watch('extent', (newExtent) => {
console.log('地图范围发生变化:', newExtent)
})
// 缩放级别变化事件
view.watch('zoom', (newZoom) => {
console.log('缩放级别变化:', newZoom)
})
}
添加图层和数据
1. 添加图形图层
import GraphicsLayer from '@geoscene/core/layers/GraphicsLayer.js'
import Graphic from '@geoscene/core/Graphic.js'
import Point from '@geoscene/core/geometry/Point.js'
import SimpleMarkerSymbol from '@geoscene/core/symbols/SimpleMarkerSymbol.js'
// 创建图形图层
const createGraphicsLayer = () => {
return new GraphicsLayer({
id: 'graphics-layer',
title: '标记图层'
})
}
// 添加点标记
const addPointMarker = (layer, longitude, latitude, attributes = {}) => {
// 创建点几何
const point = new Point({
longitude: longitude,
latitude: latitude
})
// 创建点符号
const symbol = new SimpleMarkerSymbol({
color: [226, 119, 40], // 橙色
outline: {
color: [255, 255, 255], // 白色边框
width: 2
},
size: 12
})
// 创建图形
const graphic = new Graphic({
geometry: point,
symbol: symbol,
attributes: attributes
})
// 添加到图层
layer.add(graphic)
return graphic
}
2. 添加自定义图标
import PictureMarkerSymbol from '@geoscene/core/symbols/PictureMarkerSymbol.js'
// 创建自定义图标标记
const addCustomIconMarker = (layer, longitude, latitude, iconUrl, attributes = {}) => {
const point = new Point({
longitude: longitude,
latitude: latitude
})
// 使用图片符号
const symbol = new PictureMarkerSymbol({
url: iconUrl,
width: 32,
height: 32
})
const graphic = new Graphic({
geometry: point,
symbol: symbol,
attributes: attributes
})
layer.add(graphic)
return graphic
}
// 批量添加标记点
const addMultipleMarkers = (layer, markersData) => {
const graphics = markersData.map(marker => {
return addCustomIconMarker(
layer,
marker.longitude,
marker.latitude,
marker.iconUrl,
marker.attributes
)
})
return graphics
}
3. 添加线和面
import Polyline from '@geoscene/core/geometry/Polyline.js'
import Polygon from '@geoscene/core/geometry/Polygon.js'
import SimpleLineSymbol from '@geoscene/core/symbols/SimpleLineSymbol.js'
import SimpleFillSymbol from '@geoscene/core/symbols/SimpleFillSymbol.js'
// 添加线要素
const addPolyline = (layer, paths, attributes = {}) => {
const polyline = new Polyline({
paths: paths
})
const symbol = new SimpleLineSymbol({
color: [226, 119, 40],
width: 4
})
const graphic = new Graphic({
geometry: polyline,
symbol: symbol,
attributes: attributes
})
layer.add(graphic)
return graphic
}
// 添加面要素
const addPolygon = (layer, rings, attributes = {}) => {
const polygon = new Polygon({
rings: rings
})
const symbol = new SimpleFillSymbol({
color: [227, 139, 79, 0.8], // 半透明填充
outline: {
color: [255, 255, 255],
width: 1
}
})
const graphic = new Graphic({
geometry: polygon,
symbol: symbol,
attributes: attributes
})
layer.add(graphic)
return graphic
}
交互功能实现
1. 弹窗功能
import PopupTemplate from '@geoscene/core/PopupTemplate.js'
// 创建弹窗模板
const createPopupTemplate = (title, content) => {
return new PopupTemplate({
title: title,
content: content,
// 自定义弹窗操作
actions: [
{
title: '详细信息',
id: 'show-details',
className: 'geoscene-icon-description'
},
{
title: '导航到此',
id: 'navigate-to',
className: 'geoscene-icon-navigation'
}
]
})
}
// 为图形添加弹窗
const addPopupToGraphic = (graphic, popupTemplate) => {
graphic.popupTemplate = popupTemplate
}
// 处理弹窗操作
const handlePopupActions = (view) => {
view.popup.on('trigger-action', (event) => {
const action = event.action
switch (action.id) {
case 'show-details':
console.log('显示详细信息')
// 实现详细信息逻辑
break
case 'navigate-to':
console.log('导航到此位置')
// 实现导航逻辑
break
}
})
}
2. 绘制工具
import SketchViewModel from '@geoscene/core/widgets/Sketch/SketchViewModel.js'
// 创建绘制工具
const createSketchViewModel = (view, layer) => {
return new SketchViewModel({
view: view,
layer: layer,
// 绘制符号样式
pointSymbol: new SimpleMarkerSymbol({
color: [255, 0, 0],
size: 10
}),
polylineSymbol: new SimpleLineSymbol({
color: [0, 255, 0],
width: 3
}),
polygonSymbol: new SimpleFillSymbol({
color: [0, 0, 255, 0.3],
outline: {
color: [0, 0, 255],
width: 2
}
})
})
}
// 绘制操作
const drawingOperations = {
// 开始绘制点
drawPoint: (sketchViewModel) => {
sketchViewModel.create('point')
},
// 开始绘制线
drawPolyline: (sketchViewModel) => {
sketchViewModel.create('polyline')
},
// 开始绘制面
drawPolygon: (sketchViewModel) => {
sketchViewModel.create('polygon')
},
// 取消绘制
cancel: (sketchViewModel) => {
sketchViewModel.cancel()
}
}
// 监听绘制事件
const setupDrawingEvents = (sketchViewModel) => {
// 绘制完成事件
sketchViewModel.on('create', (event) => {
if (event.state === 'complete') {
console.log('绘制完成:', event.graphic)
// 处理绘制完成的图形
handleDrawingComplete(event.graphic)
}
})
// 更新事件
sketchViewModel.on('update', (event) => {
if (event.state === 'complete') {
console.log('更新完成:', event.graphics)
}
})
// 删除事件
sketchViewModel.on('delete', (event) => {
console.log('删除图形:', event.graphics)
})
}
3. 测量工具
import DistanceMeasurement2D from '@geoscene/core/widgets/DistanceMeasurement2D.js'
import AreaMeasurement2D from '@geoscene/core/widgets/AreaMeasurement2D.js'
// 创建距离测量工具
const createDistanceMeasurement = (view) => {
const distanceMeasurement = new DistanceMeasurement2D({
view: view
})
return distanceMeasurement
}
// 创建面积测量工具
const createAreaMeasurement = (view) => {
const areaMeasurement = new AreaMeasurement2D({
view: view
})
return areaMeasurement
}
// 测量工具管理
const measurementTools = {
distanceTool: null,
areaTool: null,
// 开始距离测量
startDistanceMeasurement: (view) => {
// 清除其他测量工具
measurementTools.clearAll()
measurementTools.distanceTool = createDistanceMeasurement(view)
view.ui.add(measurementTools.distanceTool, 'top-right')
},
// 开始面积测量
startAreaMeasurement: (view) => {
// 清除其他测量工具
measurementTools.clearAll()
measurementTools.areaTool = createAreaMeasurement(view)
view.ui.add(measurementTools.areaTool, 'top-right')
},
// 清除所有测量工具
clearAll: () => {
if (measurementTools.distanceTool) {
measurementTools.distanceTool.destroy()
measurementTools.distanceTool = null
}
if (measurementTools.areaTool) {
measurementTools.areaTool.destroy()
measurementTools.areaTool = null
}
}
}
高级功能应用
1. 聚合显示
import FeatureLayer from '@geoscene/core/layers/FeatureLayer.js'
// 创建聚合图层
const createClusterLayer = (data) => {
// 创建要素图层
const featureLayer = new FeatureLayer({
source: data.map(item => ({
geometry: {
type: 'point',
longitude: item.longitude,
latitude: item.latitude
},
attributes: item.attributes
})),
objectIdField: 'ObjectID',
geometryType: 'point',
spatialReference: { wkid: 4326 },
fields: [
{
name: 'ObjectID',
alias: 'ObjectID',
type: 'oid'
},
{
name: 'name',
alias: '名称',
type: 'string'
}
],
// 启用聚合
featureReduction: {
type: 'cluster',
clusterRadius: '100px',
popupTemplate: {
title: '聚合点',
content: '此处有 {cluster_count} 个点'
},
symbol: {
type: 'simple-marker',
color: '#69dcff',
outline: {
color: 'rgba(0, 139, 174, 0.5)',
width: 15
},
size: 15
},
labelingInfo: [{
deconflictionStrategy: 'none',
labelExpressionInfo: {
expression: '$feature.cluster_count_label'
},
symbol: {
type: 'text',
color: '#004a5d',
font: {
weight: 'bold',
family: 'Noto Sans',
size: 10
}
},
labelPlacement: 'center-center'
}]
}
})
return featureLayer
}
2. 热力图
// 创建热力图图层
const createHeatmapLayer = (data) => {
const featureLayer = new FeatureLayer({
source: data,
objectIdField: 'ObjectID',
fields: [
{
name: 'ObjectID',
alias: 'ObjectID',
type: 'oid'
},
{
name: 'intensity',
alias: '强度',
type: 'double'
}
],
// 使用热力图渲染器
renderer: {
type: 'heatmap',
field: 'intensity',
colorStops: [
{ color: 'rgba(63, 40, 102, 0)', ratio: 0 },
{ color: '#472d7b', ratio: 0.083 },
{ color: '#4e2d87', ratio: 0.166 },
{ color: '#563086', ratio: 0.249 },
{ color: '#5d3280', ratio: 0.332 },
{ color: '#65337c', ratio: 0.415 },
{ color: '#6e3375', ratio: 0.498 },
{ color: '#76336e', ratio: 0.581 },
{ color: '#7f3465', ratio: 0.664 },
{ color: '#88355f', ratio: 0.747 },
{ color: '#903658', ratio: 0.83 },
{ color: '#99374f', ratio: 0.913 },
{ color: '#a23847', ratio: 1 }
],
maxPixelIntensity: 25,
minPixelIntensity: 1
}
})
return featureLayer
}