图层管理
示例
TIP
图层管理是地图应用中的一个重要功能,它允许用户控制不同地图图层的显示和隐藏,以及调整图层的透明度。本示例展示了如何实现基础的图层管理功能。
代码实现
vue
<template>
<div class="page-container">
<div class="layer-container"></div>
<div id="map"></div>
</div>
</template>
<script setup>
import { onMounted } from "vue";
onMounted(() => {
const tdtUrl =
"http://t0.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=d32c6748c80f81a44acd8633cea41dfd";
const tdtUrl2 =
"http://t0.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=d32c6748c80f81a44acd8633cea41dfd";
const map = L.map("map").setView([39.094899, 117.33083], 13);
const tdtMap = L.tileLayer(tdtUrl).addTo(map);
const layerContainer = document.querySelector(".layer-container");
const layers = [
{
name: "基础图层",
children: [
{ name: "天地图矢量", id: "tdt1", checked: true },
{ name: "天地图影像", id: "tdt2", checked: false },
],
},
];
function createLayerTree(layers, parent) {
const ul = document.createElement("ul");
layers.forEach((layer) => {
const li = document.createElement("li");
li.className = "layer-container__item";
if (layer.children) {
const span = document.createElement("span");
span.textContent = layer.name;
li.appendChild(span);
li.appendChild(createLayerTree(layer.children, li));
} else {
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.id = layer.id;
checkbox.checked = layer.checked;
checkbox.onchange = (event) => toggleLayerVisibility(event, layer.id);
const label = document.createElement("label");
label.htmlFor = layer.id;
label.textContent = layer.name;
const opacitySlider = document.createElement("input");
opacitySlider.type = "range";
opacitySlider.min = "0";
opacitySlider.max = "100";
opacitySlider.value = "100";
opacitySlider.className = "opacity-slider";
opacitySlider.id = `${layer.id}-opacity`;
opacitySlider.disabled = !layer.checked;
opacitySlider.onchange = (event) => adjustLayerOpacity(event, layer.id);
li.appendChild(checkbox);
li.appendChild(label);
li.appendChild(opacitySlider);
}
ul.appendChild(li);
});
return ul;
}
const tdt2 = L.tileLayer(tdtUrl2, { maxZoom: 18 });
const tree = createLayerTree(layers, layerContainer);
layerContainer.appendChild(tree);
function adjustLayerOpacity(event, layerId) {
const opacity = event.target.value / 100;
const layers = {
tdt1: tdtMap,
tdt2: tdt2,
};
if (layers[layerId]) {
layers[layerId].setOpacity(opacity);
}
}
function toggleLayerVisibility(event, layerType) {
const layerActions = {
tdt1: {
add: () => map.addLayer(tdtMap),
remove: () => map.removeLayer(tdtMap),
},
tdt2: {
add: () => map.addLayer(tdt2),
remove: () => map.removeLayer(tdt2),
},
};
// 获取对应的透明度滑块
const opacitySlider = document.getElementById(`${layerType}-opacity`);
// 根据图层可见性设置滑块状态
opacitySlider.disabled = !event.target.checked;
const action = layerActions[layerType];
if (action) {
if (event.target.checked) {
action.add();
} else {
action.remove();
}
}
}
});
</script>
<style scoped>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
li {
list-style: none;
}
body {
width: 100%;
height: 100vh;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, sans-serif;
}
#map {
width: 100%;
height: 100%;
}
.page-container {
display: flex;
height: 100%;
width: 100%;
}
.layer-container {
width: 320px;
background-color: rgba(255, 255, 255, 0.95);
padding: 20px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
overflow-y: auto;
}
.layer-container__item {
margin: 12px 0;
padding: 15px;
background-color: #ffffff;
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
}
.layer-container__item:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.layer-container__item span {
font-weight: 600;
color: #333;
font-size: 16px;
}
.layer-container__item label {
margin-left: 8px;
color: #444;
font-size: 14px;
}
.layer-container__item input[type="checkbox"] {
width: 16px;
height: 16px;
cursor: pointer;
}
.opacity-slider {
width: 100%;
margin-top: 12px;
height: 4px;
background: #e9ecef;
border-radius: 2px;
-webkit-appearance: none;
appearance: none;
}
.opacity-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 16px;
height: 16px;
background: #4a90e2;
border-radius: 50%;
cursor: pointer;
transition: all 0.2s ease;
}
.opacity-slider::-webkit-slider-thumb:hover {
transform: scale(1.1);
background: #357abd;
}
.opacity-slider:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.opacity-slider:disabled::-webkit-slider-thumb {
background: #999;
cursor: not-allowed;
}
.hideLayer {
display: none;
}
</style>