1.2 Openlayers调用ArcGis地图服务之动态地图(/export)
下面使用ArcGis官方服务作为示例直接调用(如果使用自己的私有服务,可能先要获取token)
各个库版本如下:
javascript
"ol": "^10.8.0",
"proj4": "^2.20.8",
"vue3-openlayers": "^12.2.2"
目录
- [1.2 动态地图【地图服务的查询接口(/export)】](#1.2 动态地图【地图服务的查询接口(/export)】)
- [1.2.1 介绍](#1.2.1 介绍)
- [1.2.2 判断](#1.2.2 判断)
- [1.2.3 调用](#1.2.3 调用)
- [1.2.3.1 在线预览](#1.2.3.1 在线预览)
- [1.2.3.2 在线调用](#1.2.3.2 在线调用)
- [1.2.3.3 Openlayers调用](#1.2.3.3 Openlayers调用)
- [1.2.3.4 Vue3-Openlayers调用](#1.2.3.4 Vue3-Openlayers调用)
- [1.2.4 对比使用调用动态地图的方式调用有切片的地图服务](#1.2.4 对比使用调用动态地图的方式调用有切片的地图服务)
- [1.2.4.1 Openlayers调用](#1.2.4.1 Openlayers调用)
1.2 动态地图【地图服务的查询接口(/export)】
1.2.1 介绍
动态地图是指服务器在收到客户端的每次请求时,根据当前请求的范围、比例尺、图层设置、样式等参数,实时渲染生成一张完整的地图图片(或切分成多个瓦片动态生成),然后返回给客户端。
核心特征:
-
实时渲染:每次请求都重新绘制地图,数据始终是最新的。
-
灵活:客户端可以动态控制显示哪些图层、应用过滤条件、改变符号样式等。
-
较高延迟:服务器需要实时进行空间查询、符号化、输出图片,对计算资源消耗大,响应速度较慢。
-
适合业务数据:常用于需要频繁更新、用户交互性强的地理信息展示(如实时监控、数据编辑、临时分析)。
-
典型应用:ArcGIS 动态地图服务(MapServer 的 /export 接口)、WMS(Web Map Service)的 GetMap 操作。
1.2.2 判断
判断一个ArcGis地图服务是否可以使用动态服务形式调用,可以查看地图服务的基本信息,比如ArcGis官方服务2
因为动态地图主要使用/export接口,所以看到下图中Supported Operations中有Export Map就基本可以判断支持动态地图

同时结合下面信息:
- 信息1


注意 :图中的Single Fused Map Cache: false和不存在Tile Info说明该地图服务没有切分缓存,可以以/export接口导出的形式支持动态地图
- 信息2

指包含两个子图层,可以在生成动态地图时使用参数控制显示隐藏
(其实在上一篇1.1.2中Single Fused Map Cache: true和存在Tile Info字段的切片地图服务,Supported Operations中也有Export Map,所以也可以以/export接口导出的形式支持动态地图,但是因为Single Fused Map Cache: true,地图图片是预先渲染好并拼接成一张大图的。因此,无论 layers 参数如何设置,它都只能返回这张已经做好的、包含了所有图层的完整图片(下面有对比))
1.2.3 调用
1.2.3.1 在线预览

点击红框内的ArcGIS JavaScript,即可在线预览

可以看到在线预览调用的是动态地图
1.2.3.2 在线调用

点击红框内的Export Map,即可在线调用

点击提交后,可以看到按照提交参数导出了layer0

1.2.3.3 Openlayers调用



可以看到,通过调整Layers参数,服务器会实时生成不同的图片,而且不像切片拼接,而是只有一个请求返回完整图片
javascript
<template>
<div class="map-page">
<h1>OpenLayers 动态地图 - Oil Sands</h1>
<div class="map-controls">
<label>
<input type="checkbox" v-model="showPoints" @change="updateLayers" />
显示项目点 (Points)
</label>
<label>
<input
type="checkbox"
v-model="showBoundaries"
@change="updateLayers"
/>
显示项目边界 (Boundaries)
</label>
</div>
<div id="dynamic-ol-map" ref="mapContainer" class="map-container"></div>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
import Map from "ol/Map";
import View from "ol/View";
import ImageLayer from "ol/layer/Image";
import ImageArcGISRest from "ol/source/ImageArcGISRest";
import { register } from "ol/proj/proj4";
import proj4 from "proj4";
const mapContainer = ref<HTMLDivElement>();
let map: Map | null = null;
// EPSG:3400 投影定义 (NAD83 / Alberta Lambert Conformal Conic)
proj4.defs(
"EPSG:3400",
"+proj=lcc +lat_1=49 +lat_2=55 +lat_0=52 +lon_0=-114.6666666666667 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs",
);
register(proj4);
// 图层显示状态
const showPoints = ref(true);
const showBoundaries = ref(true);
let dynamicLayer: ImageLayer<ImageArcGISRest> | null = null;
// 获取可见图层列表
const getVisibleLayers = () => {
const layers: string[] = [];
if (showPoints.value) layers.push("0"); // OSProjectPoints2015
if (showBoundaries.value) layers.push("1"); // OSProjectBoundaries2015
return layers;
};
// 更新图层
const updateLayers = () => {
if (dynamicLayer) {
const source = dynamicLayer.getSource();
if (source) {
source.updateParams({ LAYERS: "show:" + getVisibleLayers().join(",") });
source.refresh();
}
}
};
onMounted(() => {
// 创建 ArcGIS REST 动态地图图层
dynamicLayer = new ImageLayer({
source: new ImageArcGISRest({
ratio: 1,
params: {
LAYERS: "show:" + getVisibleLayers().join(","),
},
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/OilSandsProjectBoundaries/MapServer/export",
}),
});
// 创建地图
map = new Map({
target: mapContainer.value!,
layers: [dynamicLayer],
view: new View({
projection: "EPSG:3400",
center: [597849, 6184094], // 油砂区域中心坐标
zoom: 0,
minZoom: 0,
maxZoom: 10,
}),
});
});
onUnmounted(() => {
if (map) {
map.setTarget(undefined);
map = null;
}
});
</script>
<style scoped>
.map-page {
padding: 20px;
}
h1 {
margin-bottom: 15px;
color: #333;
}
.map-controls {
margin-bottom: 15px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.map-controls label {
display: flex;
align-items: center;
gap: 5px;
cursor: pointer;
}
.map-controls input[type="checkbox"] {
cursor: pointer;
}
.map-container {
width: 100%;
height: 600px;
border: 2px solid #ddd;
border-radius: 8px;
}
</style>
1.2.3.4 Vue3-Openlayers调用


可以看到,通过调整Layers参数,服务器会实时生成不同的图片,但是因为使用ol-tile-layer,所以的服务器返回的是多个切片,然后在浏览器拼接
javascript
<template>
<div class="map-page">
<h1>Vue3-OpenLayers 动态地图 - Oil Sands</h1>
<div class="map-controls">
<label>
<input type="checkbox" v-model="showPoints" @change="updateLayers" />
显示项目点 (Points)
</label>
<label>
<input
type="checkbox"
v-model="showBoundaries"
@change="updateLayers"
/>
显示项目边界 (Boundaries)
</label>
</div>
<ol-map
:loadTilesWhileAnimating="true"
:loadTilesWhileInteracting="true"
class="map-container"
>
<ol-view :center="center" :zoom="zoom" :projection="projection" />
<ol-tile-layer>
<OlSourceTileArcGISRest
ref="dynamicSource"
:url="mapUrl"
:params="layerParams"
/>
</ol-tile-layer>
</ol-map>
</div>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import ImageArcGISRest from "ol/source/ImageArcGISRest";
import { register } from "ol/proj/proj4";
import proj4 from "proj4";
// EPSG:3400 投影定义 (NAD83 / Alberta Lambert Conformal Conic)
proj4.defs(
"EPSG:3400",
"+proj=lcc +lat_1=49 +lat_2=55 +lat_0=52 +lon_0=-114.6666666666667 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs",
);
register(proj4);
// 图层显示状态
const showPoints = ref(true);
const showBoundaries = ref(true);
const dynamicSource = ref<{ source: ImageArcGISRest } | null>(null);
// 获取可见图层列表
const getVisibleLayers = () => {
const layers: string[] = [];
if (showPoints.value) layers.push("0"); // OSProjectPoints2015
if (showBoundaries.value) layers.push("1"); // OSProjectBoundaries2015
return layers;
};
// 图层参数
const layerParams = computed(() => ({
LAYERS: "show:" + getVisibleLayers().join(","),
}));
const mapUrl =
"https://sampleserver6.arcgisonline.com/arcgis/rest/services/OilSandsProjectBoundaries/MapServer/export";
const center = ref([597849, 6184094]); // 油砂区域中心坐标
const zoom = ref(0);
const projection = ref("EPSG:3400");
// 更新图层
const updateLayers = () => {
if (dynamicSource.value?.source) {
dynamicSource.value.source.updateParams({
LAYERS: "show:" + getVisibleLayers().join(","),
});
dynamicSource.value.source.refresh();
}
};
</script>
<style scoped>
.map-page {
padding: 20px;
}
h1 {
margin-bottom: 15px;
color: #333;
}
.map-controls {
margin-bottom: 15px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.map-controls label {
display: flex;
align-items: center;
gap: 5px;
cursor: pointer;
}
.map-controls input[type="checkbox"] {
cursor: pointer;
}
.map-container {
width: 100%;
height: 600px;
border: 2px solid #ddd;
border-radius: 8px;
overflow: hidden;
}
</style>
1.2.4 对比使用调用动态地图的方式调用有切片的地图服务
1.2.4.1 Openlayers调用
javascript
<template>
<div class="map-page">
<h1>OpenLayers 动态地图</h1>
<div class="map-controls">
<label>
<input type="checkbox" v-model="showRoads" @change="updateLayers" />
显示道路 (Roads)
</label>
<label>
<input type="checkbox" v-model="showWater" @change="updateLayers" />
显示水体 (Water)
</label>
<label>
<input type="checkbox" v-model="showUrban" @change="updateLayers" />
显示城市 (Urban)
</label>
<label>
<input type="checkbox" v-model="showLanduse" @change="updateLayers" />
显示土地 (Landuse)
</label>
</div>
<div id="dynamic-ol-map" ref="mapContainer" class="map-container"></div>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, ref } from "vue";
import Map from "ol/Map";
import View from "ol/View";
import ImageLayer from "ol/layer/Image";
import ImageArcGISRest from "ol/source/ImageArcGISRest";
const mapContainer = ref<HTMLDivElement>();
let map: Map | null = null;
// 图层显示状态
const showRoads = ref(true);
const showWater = ref(true);
const showUrban = ref(true);
const showLanduse = ref(true);
let dynamicLayer: ImageLayer<ImageArcGISRest> | null = null;
// 获取可见图层列表
const getVisibleLayers = () => {
const layers: string[] = [];
if (showRoads.value) layers.push("0"); // Roads
if (showWater.value) layers.push("1"); // Water
if (showUrban.value) layers.push("2"); // Urban
if (showLanduse.value) layers.push("3"); // Landuse
return layers;
};
// 更新图层
const updateLayers = () => {
if (dynamicLayer) {
const source = dynamicLayer.getSource();
if (source) {
source.updateParams({ LAYERS: "show:" + getVisibleLayers().join(",") });
source.refresh();
}
}
};
onMounted(() => {
// 创建 ArcGIS REST 动态地图图层
dynamicLayer = new ImageLayer({
source: new ImageArcGISRest({
ratio: 1,
params: {
LAYERS: "show:" + getVisibleLayers().join(","),
},
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/MtBaldy_BaseMap/MapServer/export",
}),
});
// 创建地图
map = new Map({
target: mapContainer.value!,
layers: [dynamicLayer],
view: new View({
projection: "EPSG:32611",
center: [457000, 3796000],
zoom: 5,
resolutions: [
4233.341800016934, 2116.670900008467, 1058.3354500042335,
529.1677250021168, 264.5838625010584, 132.2919312505292,
66.1459656252646, 33.0729828126323, 16.53649140631615,
8.268245703158074, 4.134122851579037, 2.0670614257895186,
1.0335307128947593,
],
}),
});
});
onUnmounted(() => {
if (map) {
map.setTarget(undefined);
map = null;
}
});
</script>
<style scoped>
.map-page {
padding: 20px;
}
h1 {
margin-bottom: 15px;
color: #333;
}
.map-controls {
margin-bottom: 15px;
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.map-controls label {
display: flex;
align-items: center;
gap: 5px;
cursor: pointer;
}
.map-controls input[type="checkbox"] {
cursor: pointer;
}
.map-container {
width: 100%;
height: 600px;
border: 2px solid #ddd;
border-radius: 8px;
}
</style>




可以看到,虽然Layers传参不同(新版写法为Layers show:0,1,2,3或者Layers hide:0,1,2,3 老版写法没有Layers 0,1,2),但是显示的图片都是相同的