赞
踩
本文将介绍openlayers中地图图层控制的组件制作方法,图层切换,显示隐藏,图层排序,在vue3中使用element,tree等组件。
(本专辑持续更新中)
在 OpenLayers 中,地图图层控制是一个常见的需求,包括图层的切换、显示隐藏、图层排序等。在 Vue 3 中结合 Element UI 或其他 UI 库(如 Ant Design Vue、Vuetify 等)来实现这些功能可以为用户提供一个友好的交互界面。
下面将介绍如何使用 OpenLayers、Vue 3 和 Element UI 来制作一个地图图层控制的组件。
首先,你需要在项目中安装 OpenLayers、Vue 3 和 Element UI(或其他 UI 库)。
npm install ol vue@next element-plus
在你的 Vue 组件中,你可以创建一个地图容器和一个用于控制图层的组件。
<template>
<div ref="mapContainer" class="map-container"></div>
<el-tree
:data="layersData"
node-key="id"
ref="layersTree"
@check-change="handleCheckChange"
show-checkbox
></el-tree>
</template>
<script>
import { onMounted, ref } from 'vue';
import Map from 'ol/Map';
import View from 'ol/View';
import TileLayer from 'ol/layer/Tile';
import OSM from 'ol/source/OSM';
export default {
name: 'MapComponent',
setup() {
const mapContainer = ref(null);
const layersData = ref([
{ id: 1, label: 'OpenStreetMap', visible: true },
// 其他图层数据
]);
let map;
onMounted(() => {
const osmLayer = new TileLayer({
source: new OSM(),
});
map = new Map({
target: mapContainer.value,
layers: [osmLayer],
view: new View({
center: [0, 0],
zoom: 2,
}),
});
});
function handleCheckChange(data, checked, indeterminate) {
const layerId = data.id;
// 根据图层 ID 控制图层的显示和隐藏
}
return {
mapContainer,
layersData,
handleCheckChange,
};
},
};
</script>
<style>
.map-container {
width: 100%;
height: 400px;
}
</style>
在 handleCheckChange
函数中,你可以根据图层的 ID 来控制图层的显示和隐藏。你需要维护一个图层和 OpenLayers 图层对象的映射关系,然后在该函数中切换图层的可见性。
let layersMap = {
1: osmLayer,
// 其他图层
};
function handleCheckChange(data, checked, indeterminate) {
const layerId = data.id;
const layer = layersMap[layerId];
if (layer) {
layer.setVisible(checked);
}
}
图层排序可以通过调整 map.getLayers()
返回的图层数组的顺序来实现。你可以添加一个按钮来触发图层排序的操作。
<template>
<!-- ... -->
<el-button @click="sortLayers">排序图层</el-button>
</template>
<script>
// ...
export default {
// ...
methods: {
sortLayers() {
const layers = map.getLayers().getArray().slice();
// 对 layers 数组进行排序
layers.sort((a, b) => {
// 根据你的排序规则进行比较
});
// 设置排序后的图层数组
map.getLayers().setArray(layers);
},
},
};
</script>
在上面的例子中,已经使用了 Element UI 的 Tree 组件来展示图层,并通过 checkbox 来控制图层的显示和隐藏。你可以根据需要调整 Tree 组件的属性和事件来适应你的应用场景。
ref
和 reactive
来管理状态。function getTDXYZUrl(type: string) {
return (
"http://t" +
Math.round(Math.random() * 7) +
".tianditu.com/DataServer?T=" +
type +
"&x={x}&y={y}&l={z}&tk=" +
myTDkey
);
}
const layersData = [
{
id: "1",
label: "天地图",
url: "",
opacity: 100,
visible:true,
children: [
{
id: "4",
label: "矢量注记",
url: getTDXYZUrl("cva_w"),
opacity: 100,
visible:true,
children: [],
},
{
id: "3",
label: "矢量底图",
url: getTDXYZUrl("vec_w"),
opacity: 80,
visible:true,
children: [],
},
],
},
{
id: "2",
label: "影像底图",
url: getTDXYZUrl("img_w"),
opacity: 100,
visible:true,
children: [],
},
];
function makeTree(layersData: Array<IlayersData>) {
let rootLayers: (LayerGroup | TileLayer<XYZ>)[] = [];
layersData.forEach((e) => {
if (e.children.length > 0) {
let group = new LayerGroup({
properties: {
label: e.label,
},
opacity: e.opacity!/100,
layers: makeTree(e.children),
visible:e.visible,
});
rootLayers.unshift(group);
} else {
let layer = new TileLayer({
source: new XYZ({
url: e.url,
projection: e.projection ?? "EPSG:3857",
}),
opacity: e.opacity!/100,
properties: {
label: e.label,
},
});
rootLayers.unshift(layer)
}
});
return rootLayers
}
let layers = makeTree(layersData)
function initMap(optons: { target: HTMLElement }) {
return new Map({
layers: layers,
target: optons.target as HTMLElement,
view: new View({
center: [0, 0],
zoom: 2,
}),
});
}
export {
initMap,layersData
}
<div class="whr-vertical-control " ref="my-vertical-control">
<el-popover placement="left" :width="300" trigger="hover">
<template #reference>
<!-- <el-tooltip class="box-item" effect="dark" content="图层控制" placement="top-start"> -->
<el-button type="primary" icon="CopyDocument"/>
<!-- </el-tooltip> -->
</template>
<template #default>
<div>
<div class="whr-popover-title">
<div class="yigeshu"></div>
<div class="" style="margin-left: 5px;">图层控制</div>
</div>
<el-divider/>
<div class="whr-popover-body">
<el-tree node-key="label" :data="layerTreeData" :props="defaultProps" @check-change="layerVisibleControl"
:default-checked-keys="defaultCheckedLayers"
show-checkbox>
<template #default="{ node, data }">
<span class="custom-tree-node">
<span>{{ node.label }}</span>
<span style="width: 100px;" v-if="data.children.length == 0">
<el-slider v-model="data.opacity" size="small" @change="layerOpacityChange($event,data)" />
</span>
</span>
</template>
</el-tree>
</div>
</div>
</template>
</el-popover>
</div>
class MyVerticalControl extends Control {
constructor(opt_options: any) {
const options = opt_options || {};
super({
element: self.$refs["my-vertical-control"] as HTMLElement,
target: options.target,
});
}
}
this.vercontrol = new MyVerticalControl({})
this.map = initMap({target: this.$refs.map as HTMLElement})
(this.map as Map).addControl(this.vercontrol as Control)
如果需要地图组件保活,可以把添加控件写在activated钩子里。
activated() {
(this.map as Map).addControl(this.vercontrol as Control);
},
layerVisibleControl(data: Tree,
checked: boolean,
indeterminate: boolean) {
console.log(data, checked, indeterminate)
let currentLayer = this.map!.getAllLayers().filter(e => {
return e.getProperties().label == data.label
})
if (currentLayer.length > 0) {
currentLayer[0].setVisible(checked)
}
},
layerOpacityChange($event,data){
console.log($event,data)
let currentLayer = this.map!.getAllLayers().filter(e => {
return e.getProperties().label == data.label
})
if (currentLayer.length > 0) {
currentLayer[0].setOpacity($event/100)
}
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。