openlayers基本使用(街景+标注+绘制)
卫星影像
<template>
<div class="app">
<div class="map-container" ref="map_ref"></div>
</div>
</template>
<script>
import Map from "ol/Map.js";
import TileLayer from "ol/layer/Tile.js";
import View from "ol/View.js";
import XYZ from "ol/source/XYZ.js";
export default {
data() {
return {};
},
mounted() {
this.initMap();
},
methods: {
initMap() {
// const map = new Map({
// target: this.$refs.map_ref,
// layers: [
// new TileLayer({
// source: new XYZ({
// url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
// }),
// }),
// ],
// view: new View({
// center: [0, 0],
// zoom: 2,
// }),
// });
// 创建卫星图层
const satelliteLayer = new TileLayer({
source: new XYZ({
url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
maxZoom: 18,
}),
opacity: 0.9,
zIndex: 1,
});
// 创建街道图层作为备用
const streetLayer = new TileLayer({
source: new XYZ({
url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=7&x={x}&y={y}&z={z}",
maxZoom: 18,
}),
zIndex: 0,
visible: false,
});
const map = new Map({
target: this.$refs.map_ref,
layers: [satelliteLayer, streetLayer],
view: new View({
center: [0, 0],
zoom: 2,
}),
});
},
},
};
</script>
<style lang="less" scoped>
.app {
padding: 10px;
}
.map-container {
height: calc(100vh - 50px);
// background-color: orange;
}
</style>
增加标注
基础示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>OpenLayers 街景与地名标注</title>
<!-- 引入 OpenLayers CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.css" />
<!-- 引入 OpenLayers JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.js"></script>
<style>
#map {
width: 100%;
height: 800px;
}
</style>
</head>
<body>
<div id="map"></div>
<script>
// 1.创建地图=============
var map = new ol.Map({
target: "map", // 地图渲染的目标 DOM 元素 ID
layers: [
// 底图图层,这里使用 OpenStreetMap
new ol.layer.Tile({
// source: new ol.source.OSM(),
source: new ol.source.XYZ({
url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([108, 28]), // 地图初始中心点,这里以西南地区大致经纬度为例
zoom: 8, // 初始缩放级别
}),
});
// 2.1 加载地名 GeoJSON 数据=======================
var vectorSource = new ol.source.Vector({
url: "./places.json", // 地名数据文件路径
format: new ol.format.GeoJSON(),
});
// 2.2 创建矢量图层,用于显示地名标注
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: function (feature) {
// 为每个地名要素设置样式,包括点样式和文字标签
var textStyle = new ol.style.Text({
text: feature.get("name"), // 获取地名属性
font: "12px Arial",
fill: new ol.style.Fill({
color: "#000",
}),
stroke: new ol.style.Stroke({
color: "#fff",
width: 2,
}),
offsetY: -15, // 文字相对于点的垂直偏移
});
var pointStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: "#ff0000",
}),
}),
text: textStyle,
});
return pointStyle;
},
});
// 2.3 将地名标注图层添加到地图
map.addLayer(vectorLayer);
// 3. 给地图添加点击事件,模拟街景加载
map.on("click", function (evt) {
var coordinate = evt.coordinate;
// 这里只是模拟,实际需根据点击位置获取街景资源并展示
alert("点击位置经纬度:" + ol.proj.toLonLat(coordinate));
// 实际项目中,可在此处调用街景库的 API 加载对应位置的街景
});
// 获取地图的缩放级别=================start
// 获取地图视图对象
const view = map.getView();
// 监听change:resolution事件
view.on("change:resolution", function () {
const zoom = view.getZoom(); // 获取当前缩放级别
console.log("zoom=========>", zoom);
});
// 获取地图的缩放级别=================end
</script>
</body>
</html>
缩放到一定程度后再显示标注
效果图:

示例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>OpenLayers 街景与地名标注</title>
<!-- 引入 OpenLayers CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.css" />
<!-- 引入 OpenLayers JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.js"></script>
<style>
#map {
width: 100%;
height: 800px;
}
</style>
</head>
<body>
<div class="info">
当前缩放级别: <span id="zoom-level">0</span><br />
标注将在缩放级别 ≥ 8 时显示
</div>
<div id="map"></div>
<script>
// 1.创建地图=============
var map = new ol.Map({
target: "map", // 地图渲染的目标 DOM 元素 ID
layers: [
// 底图图层,这里使用 OpenStreetMap
new ol.layer.Tile({
// source: new ol.source.OSM(),
source: new ol.source.XYZ({
url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([108, 28]), // 地图初始中心点,这里以西南地区大致经纬度为例
zoom: 8, // 初始缩放级别
}),
});
// 2.1 加载地名 GeoJSON 数据=======================
var vectorSource = new ol.source.Vector({
url: "./places.json", // 地名数据文件路径
format: new ol.format.GeoJSON(),
});
// 2.2 创建矢量图层,用于显示地名标注
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: function (feature) {
// 为每个地名要素设置样式,包括点样式和文字标签
var textStyle = new ol.style.Text({
text: feature.get("name"), // 获取地名属性
font: "12px Arial",
fill: new ol.style.Fill({
color: "#000",
}),
stroke: new ol.style.Stroke({
color: "#fff",
width: 2,
}),
offsetY: -15, // 文字相对于点的垂直偏移
});
var pointStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: "#ff0000",
}),
}),
text: textStyle,
});
return pointStyle;
},
});
// 2.3 将地名标注图层添加到地图
map.addLayer(vectorLayer);
// 3. 需求:获取地图的经纬度 (给地图添加点击事件)
map.on("click", function (evt) {
var coordinate = evt.coordinate;
// 这里只是模拟,实际需根据点击位置获取街景资源并展示
alert("点击位置经纬度:" + ol.proj.toLonLat(coordinate));
// 实际项目中,可在此处调用街景库的 API 加载对应位置的街景
});
// 4. 需求:缩放到一定的程度后再显示标注图层============start
// 缩放级别显示元素
var zoomLevelElement = document.getElementById("zoom-level");
// 控制标注显示的最小缩放级别
var MIN_ZOOM_FOR_LABELS = 8;
// 更新标注可见性的函数
function updateLabelsVisibility() {
var currentZoom = map.getView().getZoom();
zoomLevelElement.textContent = currentZoom.toFixed(1);
// 当缩放级别大于等于设定值时显示标注,否则隐藏
vectorLayer.setVisible(currentZoom >= MIN_ZOOM_FOR_LABELS);
}
// 初始调用一次,设置初始状态
updateLabelsVisibility();
// 监听地图的移动结束事件(包括缩放和拖动)
map.on("moveend", updateLabelsVisibility);
// 4. 需求:缩放到一定的程度后再显示标注图层============end
</script>
</body>
</html>
多边形绘制和标记
基础示例
效果图:

示例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>OpenLayers 街景与地名标注</title>
<!-- 引入 OpenLayers CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.css" />
<!-- 引入 OpenLayers JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.js"></script>
<style>
#map {
width: 100%;
height: 800px;
}
.info {
/* position: absolute;
top: 10px;
left: 10px; */
background: white;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
/* max-width: 250px; */
}
/* 绘制工具 */
.toolbar {
/* position: absolute;
top: 10px;
right: 10px; */
background: white;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
}
.toolbar button {
/* display: block;
width: 100%; */
padding: 8px 12px;
margin-bottom: 5px;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s;
}
.toolbar button:hover {
background: #e0e0e0;
}
.toolbar button.active {
background: #4285f4;
color: white;
border-color: #4285f4;
}
.status-panel {
background: white;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
max-height: 200px;
overflow-y: auto;
}
.feature-count {
color: #666;
font-size: 14px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<div class="info">
当前缩放级别: <span id="zoom-level">0</span><br />
标注将在缩放级别 ≥ 8 时显示
</div>
<div class="toolbar">
<button id="draw-point">绘制点标记</button>
<button id="draw-line-string">绘制线</button>
<button id="draw-polygon">绘制多边形</button>
<button id="clear">清除所有绘制</button>
</div>
<div class="data-panel">
<h4>绘制数据信息:</h4>
<pre id="data-display"></pre>
</div>
<!-- <div class="data-panel">
<h4>绘制数据信息:</h4>
<pre id="latest-data"></pre>
<div class="history-list">
<h5>历史绘制记录:</h5>
<ul id="history-data"></ul>
</div>
</div> -->
<div class="status-panel">
<div class="feature-count">当前已绘制: <span id="count">0</span> 个要素</div>
<div>
<h4>最近绘制数据:</h4>
<pre id="last-feature-data"></pre>
</div>
</div>
<div id="map"></div>
<script>
var map = new ol.Map({
target: "map",
layers: [
// 底图图层,这里使用 OpenStreetMap
new ol.layer.Tile({
// source: new ol.source.OSM(),
source: new ol.source.XYZ({
url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([108, 28]),
zoom: 8,
}),
});
var vectorSource = new ol.source.Vector({
url: "./places.json", // 地名数据文件路径
format: new ol.format.GeoJSON(),
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: function (feature) {
var textStyle = new ol.style.Text({
text: feature.get("name"), // 获取地名属性
font: "12px Arial",
fill: new ol.style.Fill({
color: "#000",
}),
stroke: new ol.style.Stroke({
color: "#fff",
width: 2,
}),
offsetY: -15, // 文字相对于点的垂直偏移
});
var pointStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: "#ff0000",
}),
}),
text: textStyle,
});
return pointStyle;
},
});
map.addLayer(vectorLayer);
map.on("click", function (evt) {
var coordinate = evt.coordinate;
console.log("点击位置经纬度:" + ol.proj.toLonLat(coordinate));
});
var zoomLevelElement = document.getElementById("zoom-level");
var MIN_ZOOM_FOR_LABELS = 8;
function updateLabelsVisibility() {
var currentZoom = map.getView().getZoom();
zoomLevelElement.textContent = currentZoom.toFixed(1);
vectorLayer.setVisible(currentZoom >= MIN_ZOOM_FOR_LABELS);
}
updateLabelsVisibility();
map.on("moveend", updateLabelsVisibility);
// 绘制
// 绘制交互变量
let draw;
// 创建矢量数据源和图层
const vector_source = new ol.source.Vector();
// 创建矢量图层并关联数据源
const vector_layer = new ol.layer.Vector({
source: vector_source,
style: new ol.style.Style({
fill: new ol.style.Fill({ color: "rgba(0, 153, 255, 0.2)" }),
stroke: new ol.style.Stroke({ color: "#0099ff", width: 2 }),
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({ color: "#0099ff" }),
stroke: new ol.style.Stroke({ color: "white", width: 1 }),
}),
}),
});
map.addLayer(vector_layer);
const dataDisplay = document.getElementById("data-display");
const countElement = document.getElementById("count");
const lastFeatureElement = document.getElementById("last-feature-data");
// 更新要素计数显示
function updateFeatureCount() {
const count = vector_source.getFeatures().length;
countElement.textContent = count;
}
// 激活绘制工具的函数
function activateDraw(type, id) {
// 移除现有的绘制交互
if (draw) {
map.removeInteraction(draw);
}
// 清除按钮的active状态
document.querySelectorAll(".toolbar button").forEach((btn) => {
btn.classList.remove("active");
});
// 如果不是清除操作,则激活相应的绘制工具
if (type !== "clear") {
document.getElementById(id).classList.add("active");
// 创建新的绘制交互
draw = new ol.interaction.Draw({
// 绘制的内容会添加到这个数据源
source: vector_source,
type: type,
});
map.addInteraction(draw);
// 监听绘制结束事件
draw.on("drawend", function (event) {
// 获取绘制的要素
const feature = event.feature;
// 获取几何图形
const geometry = feature.getGeometry();
// 根据几何类型处理数据
let data, type;
switch (geometry.getType()) {
case "Point":
type = "点";
// OpenLayers 默认使用 Web Mercator 投影坐标(米为单位),转换为经纬度坐标(度为单位)
const coords = ol.proj.toLonLat(geometry.getCoordinates());
data = `坐标: [${coords[0].toFixed(6)}, ${coords[1].toFixed(6)}]`;
break;
case "LineString":
type = "线";
// 线的坐标数组
const lineCoords = geometry
.getCoordinates()
.map((coord) => ol.proj.toLonLat(coord))
.map((coord) => `[${coord[0].toFixed(6)}, ${coord[1].toFixed(6)}]`);
data = `路径点: [\n ${lineCoords.join(",\n ")}\n]`;
break;
case "Polygon":
type = "多边形";
// 多边形的坐标数组(外层数组是多边形环,取第一个环)
const polygonCoords = geometry
.getCoordinates()[0]
.map((coord) => ol.proj.toLonLat(coord))
.map((coord) => `[${coord[0].toFixed(6)}, ${coord[1].toFixed(6)}]`);
data = `顶点: [\n ${polygonCoords.join(",\n ")}\n]`;
break;
}
// 显示数据
dataDisplay.textContent = `绘制了${type}:\n${data}\n\n历史数据可通过vectorSource获取`;
lastFeatureElement.textContent = data;
// 更新要素计数
// 确保添加完成后再更新计数
setTimeout(() => {
updateFeatureCount();
}, 200);
});
}
}
// 绑定按钮事件
document.getElementById("draw-point").addEventListener("click", () => {
activateDraw("Point", "draw-point");
});
document.getElementById("draw-line-string").addEventListener("click", () => {
activateDraw("LineString", "draw-line-string");
});
document.getElementById("draw-polygon").addEventListener("click", () => {
activateDraw("Polygon", "draw-polygon");
});
document.getElementById("clear").addEventListener("click", () => {
// 清除所有绘制的要素
vector_source.clear();
// 移除绘制交互
if (draw) {
map.removeInteraction(draw);
draw = null;
}
// 清除按钮的active状态
document.querySelectorAll(".toolbar button").forEach((btn) => {
btn.classList.remove("active");
dataDisplay.textContent = "所有绘制已清除";
// 更新显示
lastFeatureElement.textContent = "所有要素已清除";
updateFeatureCount();
});
});
</script>
</body>
</html>
增加信息窗
效果图:

示例代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<title>OpenLayers 街景与地名标注</title>
<!-- 引入 OpenLayers CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.css" />
<!-- 引入 OpenLayers JavaScript -->
<script src="https://cdn.jsdelivr.net/npm/ol@7.5.1/dist/ol.js"></script>
<style>
#map {
width: 100%;
height: 800px;
}
.info {
/* position: absolute;
top: 10px;
left: 10px; */
background: white;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
/* max-width: 250px; */
}
/* 绘制工具 */
.toolbar {
/* position: absolute;
top: 10px;
right: 10px; */
background: white;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
}
.toolbar button {
/* display: block;
width: 100%; */
padding: 8px 12px;
margin-bottom: 5px;
background: #f5f5f5;
border: 1px solid #ddd;
border-radius: 3px;
cursor: pointer;
transition: all 0.2s;
}
.toolbar button:hover {
background: #e0e0e0;
}
.toolbar button.active {
background: #4285f4;
color: white;
border-color: #4285f4;
}
.status-panel {
background: white;
padding: 10px;
border-radius: 5px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.2);
max-height: 200px;
overflow-y: auto;
}
.feature-count {
color: #666;
font-size: 14px;
margin-bottom: 10px;
}
/* 信息弹窗样式 */
.popup {
position: absolute;
background-color: white;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
pointer-events: auto;
display: none;
}
.popup-content {
min-width: 200px;
}
.popup-closer {
position: absolute;
top: 5px;
right: 5px;
cursor: pointer;
font-size: 16px;
}
</style>
</head>
<body>
<div class="info">
当前缩放级别: <span id="zoom-level">0</span><br />
标注将在缩放级别 ≥ 8 时显示
</div>
<div class="toolbar">
<button id="draw-point">绘制点标记</button>
<button id="draw-line-string">绘制线</button>
<button id="draw-polygon">绘制多边形</button>
<button id="clear">清除所有绘制</button>
<button id="save">保存</button>
</div>
<div class="data-panel">
<h4>绘制数据信息:</h4>
<pre id="data-display"></pre>
</div>
<!-- <div class="data-panel">
<h4>绘制数据信息:</h4>
<pre id="latest-data"></pre>
<div class="history-list">
<h5>历史绘制记录:</h5>
<ul id="history-data"></ul>
</div>
</div> -->
<div class="status-panel">
<div class="feature-count">当前已绘制: <span id="count">0</span> 个要素</div>
<div>
<h4>最近绘制数据:</h4>
<pre id="last-feature-data"></pre>
</div>
</div>
<!-- 信息弹窗 -->
<div id="popup" class="popup">
<a href="#" class="popup-closer" onclick="hidePopup()">×</a>
<div id="popup-content" class="popup-content"></div>
</div>
<div id="map"></div>
<script>
var map = new ol.Map({
target: "map",
layers: [
// 底图图层,这里使用 OpenStreetMap
new ol.layer.Tile({
// source: new ol.source.OSM(),
source: new ol.source.XYZ({
url: "https://webst0{1-4}.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",
}),
}),
],
view: new ol.View({
center: ol.proj.fromLonLat([108, 28]),
zoom: 8,
}),
});
var vectorSource = new ol.source.Vector({
url: "./places.json", // 地名数据文件路径
format: new ol.format.GeoJSON(),
});
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: function (feature) {
var textStyle = new ol.style.Text({
text: feature.get("name"), // 获取地名属性
font: "12px Arial",
fill: new ol.style.Fill({
color: "#000",
}),
stroke: new ol.style.Stroke({
color: "#fff",
width: 2,
}),
offsetY: -15, // 文字相对于点的垂直偏移
});
var pointStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill({
color: "#ff0000",
}),
}),
text: textStyle,
});
return pointStyle;
},
});
map.addLayer(vectorLayer);
map.on("click", function (evt) {
var coordinate = evt.coordinate;
console.log("点击位置经纬度:" + ol.proj.toLonLat(coordinate));
// 检查点击位置是否有要素
map.forEachFeatureAtPixel(evt.pixel, function (feature) {
// 核心过滤逻辑:排除临时要素(只有带 isFinished: true 的才是正式要素)
// 如果点击的是多边形
// if (feature.get("isFinished") && feature.getGeometry() instanceof ol.geom.Polygon) {
// showPopup(evt.coordinate, feature);
// return true; // 停止遍历
// }
if (feature.get("isFinished")) {
showPopup(evt.coordinate, feature);
return true; // 停止遍历
}
});
});
var zoomLevelElement = document.getElementById("zoom-level");
var MIN_ZOOM_FOR_LABELS = 8;
function updateLabelsVisibility() {
var currentZoom = map.getView().getZoom();
zoomLevelElement.textContent = currentZoom.toFixed(1);
vectorLayer.setVisible(currentZoom >= MIN_ZOOM_FOR_LABELS);
}
updateLabelsVisibility();
map.on("moveend", updateLabelsVisibility);
// 绘制
// 绘制交互变量
let draw;
// 创建矢量数据源和图层
const vector_source = new ol.source.Vector();
// 创建矢量图层并关联数据源
const vector_layer = new ol.layer.Vector({
source: vector_source,
style: new ol.style.Style({
fill: new ol.style.Fill({ color: "rgba(0, 153, 255, 0.2)" }),
stroke: new ol.style.Stroke({ color: "#0099ff", width: 2 }),
image: new ol.style.Circle({
radius: 6,
fill: new ol.style.Fill({ color: "#0099ff" }),
stroke: new ol.style.Stroke({ color: "white", width: 1 }),
}),
}),
});
map.addLayer(vector_layer);
const dataDisplay = document.getElementById("data-display");
const countElement = document.getElementById("count");
const lastFeatureElement = document.getElementById("last-feature-data");
const saveElement = document.getElementById("save");
// 更新要素计数显示
function updateFeatureCount() {
const count = vector_source.getFeatures().length;
countElement.textContent = count;
}
// 计算多边形面积(平方米)
function calculateArea(geometry) {
const area = geometry.getArea();
// 转换为平方米(如果需要)
return Math.round(area) + " 平方米";
}
// 激活绘制工具的函数
function activateDraw(type, id) {
// 移除现有的绘制交互
if (draw) {
map.removeInteraction(draw);
}
// 清除按钮的active状态
document.querySelectorAll(".toolbar button").forEach((btn) => {
btn.classList.remove("active");
});
// 如果不是清除操作,则激活相应的绘制工具
if (type !== "clear") {
document.getElementById(id).classList.add("active");
// 创建新的绘制交互
draw = new ol.interaction.Draw({
// 绘制的内容会添加到这个数据源
source: vector_source,
type: type,
});
map.addInteraction(draw);
// 监听绘制结束事件
draw.on("drawend", function (event) {
// event.stopPropagation();
draw.setActive(false);
// 获取绘制的要素
const feature = event.feature;
// 获取几何图形
const geometry = feature.getGeometry();
// 给正式要素添加标识(用于后续弹窗过滤)
feature.set("isFinished", true);
// 添加其他属性(如面积)
// 多边形
// feature.set("area", Math.round(geometry.getArea()) + " 平方米");
// feature.set("name", "多边形" + vector_source.getFeatures().length);
feature.set("test_data", {
name: "zs",
age: 36,
friend: ["kobe", "lili"],
});
// 根据几何类型处理数据
let data, type;
switch (geometry.getType()) {
case "Point":
type = "点";
// OpenLayers 默认使用 Web Mercator 投影坐标(米为单位),转换为经纬度坐标(度为单位)
const coords = ol.proj.toLonLat(geometry.getCoordinates());
data = `坐标: [${coords[0].toFixed(6)}, ${coords[1].toFixed(6)}]`;
break;
case "LineString":
type = "线";
// 线的坐标数组
const lineCoords = geometry
.getCoordinates()
.map((coord) => ol.proj.toLonLat(coord))
.map((coord) => `[${coord[0].toFixed(6)}, ${coord[1].toFixed(6)}]`);
data = `路径点: [\n ${lineCoords.join(",\n ")}\n]`;
break;
case "Polygon":
type = "多边形";
// 多边形的坐标数组(外层数组是多边形环,取第一个环)
const polygonCoords = geometry
.getCoordinates()[0]
.map((coord) => ol.proj.toLonLat(coord))
.map((coord) => `[${coord[0].toFixed(6)}, ${coord[1].toFixed(6)}]`);
data = `顶点: [\n ${polygonCoords.join(",\n ")}\n]`;
break;
}
// 显示数据
dataDisplay.textContent = `绘制了${type}:\n${data}\n\n历史数据可通过vectorSource获取`;
lastFeatureElement.textContent = data;
// 更新要素计数
// 确保添加完成后再更新计数
setTimeout(() => {
updateFeatureCount();
}, 200);
});
}
}
// 绑定按钮事件
document.getElementById("draw-point").addEventListener("click", () => {
activateDraw("Point", "draw-point");
});
document.getElementById("draw-line-string").addEventListener("click", () => {
activateDraw("LineString", "draw-line-string");
});
document.getElementById("draw-polygon").addEventListener("click", () => {
activateDraw("Polygon", "draw-polygon");
});
document.getElementById("clear").addEventListener("click", () => {
// 清除所有绘制的要素
vector_source.clear();
// 移除绘制交互
if (draw) {
map.removeInteraction(draw);
draw = null;
}
// 清除按钮的active状态
document.querySelectorAll(".toolbar button").forEach((btn) => {
btn.classList.remove("active");
dataDisplay.textContent = "所有绘制已清除";
// 更新显示
lastFeatureElement.textContent = "所有要素已清除";
updateFeatureCount();
});
});
document.getElementById("save").addEventListener("click", () => {
if (draw) {
map.removeInteraction(draw);
}
});
// 显示弹窗
function showPopup(coordinate, feature) {
const popup = document.getElementById("popup");
const popupContent = document.getElementById("popup-content");
// 设置弹窗内容
// 示例:多边形
// popupContent.innerHTML = `
// <h3>${feature.get("name")}</h3>
// <p>面积: ${feature.get("area")}</p>
// <p>ID: ${feature.getId()}</p>
// `;
const test_data = feature.get("test_data");
popupContent.innerHTML = `
<h1>测试数据</h1>
<h3>姓名:${test_data.name}</h3>
<h3>年龄:${test_data.age}</h3>
<h3>朋友:${JSON.stringify(test_data.friend)}</h3>
`;
console.log("dddddd==>", feature.get("test_data"));
// 设置弹窗位置
const overlay = new ol.Overlay({
element: popup,
positioning: "bottom-center",
stopEvent: false,
offset: [0, -10],
});
map.addOverlay(overlay);
overlay.setPosition(coordinate);
// 显示弹窗
popup.style.display = "block";
}
// 隐藏弹窗
function hidePopup() {
const popup = document.getElementById("popup");
popup.style.display = "none";
}
// 鼠标悬停时改变光标样式
map.on("pointermove", function (e) {
const pixel = map.getEventPixel(e.originalEvent);
const hit = map.hasFeatureAtPixel(pixel);
map.getTargetElement().style.cursor = hit ? "pointer" : "";
});
</script>
</body>
</html>

浙公网安备 33010602011771号