共享视图
和分屏对比案例不同,共享视图案例是两个地图共享同一个View对象
介绍
- 两个地图共享同一个View对象,这样它们的缩放和平移会保持同步
展开代码
vue
<template>
<div class="map-container">
<div class="map-wrapper">
<div class="map-section">
<h3>路网地图</h3>
<div ref="roadMapContainer" class="map"></div>
</div>
<div class="map-section">
<h3>卫星地图</h3>
<div ref="aerialMapContainer" class="map"></div>
</div>
</div>
<div class="controls">
<div class="info">
<h4>视图共享演示</h4>
<p>两个地图共享同一个视图,缩放和平移会同步</p>
<p>当前缩放级别: {{ currentZoom }}</p>
<p>当前中心点: {{ currentCenter }}</p>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import XYZ from 'ol/source/XYZ';
import 'ol/ol.css';
const roadMapContainer = ref(null);
const aerialMapContainer = ref(null);
let map1 = null;
let map2 = null;
let sharedView = null;
// 响应式变量
const currentZoom = ref(10);
const currentCenter = ref([0, 0]);
// 更新视图信息
const updateViewInfo = () => {
if (sharedView) {
currentZoom.value = Math.round(sharedView.getZoom() * 100) / 100;
const center = sharedView.getCenter();
currentCenter.value = [
Math.round(center[0] * 1000) / 1000,
Math.round(center[1] * 1000) / 1000
];
}
};
onMounted(() => {
// 创建路网图层
const roadLayer = new TileLayer({
source: new XYZ({
url: "https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}",
}),
});
// 创建卫星图层
const aerialLayer = new TileLayer({
source: new XYZ({
url: "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
});
// 创建共享视图 - 关键:两个地图使用同一个View实例
sharedView = new View({
center: [116.4074, 39.9042], // 北京市中心经纬度
zoom: 10,
projection: "EPSG:4326",
});
sharedView = new View({
center: [116.4074, 39.9042], // 北京市中心经纬度
zoom: 10,
projection: "EPSG:4326",
});
// 创建第一个地图(路网)
map1 = new Map({
target: roadMapContainer.value,
layers: [roadLayer],
view: sharedView, // 使用共享视图
});
// 创建第二个地图(卫星)
map2 = new Map({
target: aerialMapContainer.value,
layers: [aerialLayer],
view: sharedView, // 使用同一个共享视图
});
// 监听视图变化
sharedView.on('change:resolution', updateViewInfo);
sharedView.on('change:center', updateViewInfo);
// 初始化视图信息
updateViewInfo();
});
onUnmounted(() => {
// 清理资源
if (map1) {
map1.setTarget(undefined);
map1 = null;
}
if (map2) {
map2.setTarget(undefined);
map2 = null;
}
if (sharedView) {
sharedView.un('change:resolution', updateViewInfo);
sharedView.un('change:center', updateViewInfo);
sharedView = null;
}
});
</script>
<style scoped>
.map-container {
width: 100vw;
height: 100vh;
position: relative;
font-family: sans-serif;
display: flex;
flex-direction: column;
}
.map-wrapper {
flex: 1;
display: flex;
gap: 2px;
}
.map-section {
flex: 1;
display: flex;
flex-direction: column;
}
.map-section h3 {
margin: 0;
padding: 10px;
background-color: rgba(0, 0, 0, 0.8);
color: white;
text-align: center;
font-size: 16px;
font-weight: 500;
}
.map {
flex: 1;
min-height: 0;
}
.controls {
position: absolute;
top: 10px;
left: 10px;
z-index: 1000;
background-color: rgba(255, 255, 255, 0.9);
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
min-width: 250px;
}
.info h4 {
margin: 0 0 10px 0;
color: #495057;
font-size: 16px;
}
.info p {
margin: 5px 0;
font-size: 14px;
color: #666;
}
</style>