测量距离
在地图上测量两点之间的距离;
<!DOCTYPE html>
<html lang="en">
<head>
<title>测量距离</title>
<meta property="og:description" content="在地图上测量两点之间的距离" />
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.css' />
<script src='https://unpkg.com/maplibre-gl@5.5.0/dist/maplibre-gl.js'></script>
<style>
body { margin: 0; padding: 0; }
html, body, #map { height: 100%; }
.distance-container {
position: absolute;
top: 10px;
left: 10px;
z-index: 1;
}
.distance-container > * {
background-color: rgba(255, 255, 255, 0.9);
border-radius: 4px;
padding: 10px;
margin-bottom: 5px;
font-family: 'Arial', sans-serif;
font-size: 14px;
color: #333;
}
.distance-container button {
background-color: #4285F4;
color: white;
border: none;
padding: 6px 12px;
border-radius: 4px;
font-size: 14px;
font-weight: bold;
cursor: pointer;
}
.distance-container button:hover {
background-color: #3367D6;
}
.distance-result {
background-color: white;
padding: 8px 12px;
margin-top: 10px;
border-radius: 4px;
display: none;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
</style>
</head>
<body>
<div id="map"></div>
<div class="distance-container">
<div>
<h3 style="margin: 0 0 10px 0;">测量距离</h3>
<p style="margin: 0 0 10px 0;">点击开始按钮,然后在地图上点击两个点测量它们之间的距离。</p>
<button id="start-measuring">开始测量</button>
<button id="clear-points" style="margin-left: 5px; background-color: #999;">清除</button>
<div id="distance-result" class="distance-result"></div>
</div>
</div>
<script>
const map = new maplibregl.Map({
container: 'map',
style: 'https://api.maptiler.com/maps/streets/style.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
center: [0, 0],
zoom: 2
});
// 添加导航控件
map.addControl(new maplibregl.NavigationControl());
// 测量状态变量
let isActive = false;
let points = [];
let markers = [];
let measureLine = null;
// 获取UI元素
const startBtn = document.getElementById('start-measuring');
const clearBtn = document.getElementById('clear-points');
const distanceResult = document.getElementById('distance-result');
// 开始测量按钮
startBtn.addEventListener('click', function() {
if (!isActive) {
isActive = true;
this.textContent = '正在测量...';
this.style.backgroundColor = '#db4437';
map.getCanvas().style.cursor = 'crosshair';
} else {
isActive = false;
this.textContent = '开始测量';
this.style.backgroundColor = '#4285F4';
map.getCanvas().style.cursor = '';
}
});
// 清除按钮
clearBtn.addEventListener('click', function() {
clearMeasurement();
startBtn.textContent = '开始测量';
startBtn.style.backgroundColor = '#4285F4';
isActive = false;
map.getCanvas().style.cursor = '';
});
// 地图点击事件
map.on('click', function(e) {
if (!isActive) return;
const lngLat = e.lngLat;
// 添加点到数组
points.push(lngLat);
// 创建标记
const marker = new maplibregl.Marker({
color: points.length === 1 ? '#1e88e5' : '#e53935'
})
.setLngLat(lngLat)
.addTo(map);
markers.push(marker);
// 如果有两个点,绘制线并计算距离
if (points.length === 2) {
drawMeasurementLine();
calculateDistance();
isActive = false;
startBtn.textContent = '开始测量';
startBtn.style.backgroundColor = '#4285F4';
map.getCanvas().style.cursor = '';
}
});
// 绘制测量线
function drawMeasurementLine() {
// 如果已存在旧的线,先移除
if (map.getSource('measure-line')) {
map.removeLayer('measure-line-layer');
map.removeSource('measure-line');
}
map.addSource('measure-line', {
'type': 'geojson',
'data': {
'type': 'Feature',
'properties': {},
'geometry': {
'type': 'LineString',
'coordinates': [
[points[0].lng, points[0].lat],
[points[1].lng, points[1].lat]
]
}
}
});
map.addLayer({
'id': 'measure-line-layer',
'type': 'line',
'source': 'measure-line',
'layout': {
'line-join': 'round',
'line-cap': 'round'
},
'paint': {
'line-color': '#f44336',
'line-width': 3,
'line-dasharray': [2, 1]
}
});
}
// 计算距离
function calculateDistance() {
// 使用Haversine公式计算距离
const distance = calculateHaversineDistance(
points[0].lat, points[0].lng,
points[1].lat, points[1].lng
);
let distanceText;
if (distance >= 1000) {
distanceText = `${(distance / 1000).toFixed(2)} 公里`;
} else {
distanceText = `${Math.round(distance)} 米`;
}
// 显示结果
distanceResult.textContent = `两点距离: ${distanceText}`;
distanceResult.style.display = 'block';
}
// Haversine公式计算球面距离
function calculateHaversineDistance(lat1, lon1, lat2, lon2) {
const R = 6371000; // 地球半径,单位:米
const dLat = toRadians(lat2 - lat1);
const dLon = toRadians(lon2 - lon1);
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
return distance;
}
// 将角度转换为弧度
function toRadians(degrees) {
return degrees * Math.PI / 180;
}
// 清除测量
function clearMeasurement() {
// 清除标记
markers.forEach(marker => marker.remove());
markers = [];
// 清除线
if (map.getSource('measure-line')) {
map.removeLayer('measure-line-layer');
map.removeSource('measure-line');
}
// 重置状态
points = [];
distanceResult.style.display = 'none';
}
</script>
</body>
</html>