Openlayers调用ArcGis地图服务之二 —— 动态地图(/export)

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),但是显示的图片都是相同的

相关推荐
Chengbei112 小时前
全新开源 Burp AI 扫描插件、支持 17 类 Web检测,自带 WAF 绕过,一键自动化挖掘并智能验证
前端·人工智能·自动化
漂视数字孪生世界2 小时前
2026 SMT工厂数字孪生开发实战选型指南
数据可视化
爱宇阳2 小时前
HTML头部元信息避坑指南
前端·html
ZC跨境爬虫2 小时前
UI前端美化技能提升日志day6:(使用苹果字体+计算样式对比差异)
前端·javascript·css·ui·状态模式
胡志辉的博客2 小时前
前端反调试:常见套路、识别方法与绕过思路
前端·javascript·web安全·状态模式·安全威胁分析·代码混淆
牛奶2 小时前
老板问我接口设计,我甩给他一个文档
前端·restful·graphql
山海鲸可视化2 小时前
数字孪生项目案例 | 冷链物流可视化-园区篇
大数据·数据分析·数据可视化·数据看板·可视化大屏
gskyi2 小时前
uni-app 高阶实战:onLoad与getCurrentPages深度技巧
前端·javascript·vue.js·uni-app
月明水寒2 小时前
IDEA2026.1 vue文件报错
前端·javascript·vue.js·intellij-idea·idea·intellij idea