您的组件需要在那里更改两个项目
API Endpoint:后来,您改用https://overpass-api.de/api/interpreter,这是专门为OpenStreetMap数据库上复杂而广泛的查询而设计的.
而不是GET
,应该是POST
呼叫.
Query Format:立交桥QL中的查询格式可能得到了增强,包括更具体的参数、过滤器或边界框坐标,以获取更有针对性的数据,如特定半径内的建筑物.
更多文档在这里
Overpass QL个
Overpass API Wiki个
Overpass Turbo个
Wrong URL
https://api.openstreetmap.org/api/interpreter
Correct URL
https://overpass-api.de/api/interpreter
text
格式正文
[out:json];
(
// Fetch buildings in a specific area
way["building"](around:3000,59.132659900251944, 9.727169813491393);
);
out body;
>;
out skel qt;
Demo component
另存为‘MapComponent.js’
import React, { useState, useEffect, useRef, useCallback } from 'react';
import axios from 'axios';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import * as turf from '@turf/turf';
const MapComponent = () => {
const [buildingData, setBuildingData] = useState(null);
const [area, setArea] = useState(0);
const mapRef = useRef(null);
// Initialize the map
useEffect(() => {
if (!mapRef.current) {
mapRef.current = L.map('map').setView([59.132659900251944, 9.727169813491393], 13); // Centered on Paris
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(mapRef.current);
}
}, []);
// Fetch building data
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.post(
'https://overpass-api.de/api/interpreter',
`[out:json];(way["building"](around:3000,59.132659900251944, 9.727169813491393););out body;>;out skel qt;`,
{
headers: { 'Content-Type': 'text/plain' }
}
);
setBuildingData(response.data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, []);
const calculateAndDisplayArea = useCallback(() => {
if (buildingData && mapRef.current) {
let totalArea = 0;
const nodeMapping = {}; // Assuming you have this mapping from node ID to { lat, lon }
buildingData.elements.forEach(element => {
if (element.type === 'node') {
nodeMapping[element.id] = { lat: element.lat, lon: element.lon };
}
});
const features = buildingData.elements.filter(element => element.type === 'way');
features.forEach(feature => {
if (feature.nodes && feature.nodes.length > 0) {
const coordinates = feature.nodes.map(nodeId => {
const node = nodeMapping[nodeId];
return [node.lat, node.lon];
});
if (coordinates.length > 0) {
L.polygon(coordinates).addTo(mapRef.current); // Add polygon to map
const geoJsonPolygon = {
type: 'Polygon',
coordinates: [coordinates.map(coord => [coord[1], coord[0]])], // Convert to [lon, lat]
};
totalArea += turf.area(geoJsonPolygon);
}
}
});
setArea(totalArea);
}
}, [buildingData]);
useEffect(() => {
calculateAndDisplayArea();
}, [calculateAndDisplayArea, buildingData]);
return (
<div>
<p>Area: {area.toFixed(2)} square meters</p>
<div id="map" style={{ height: '800px', width: '1000px', margin: '0 auto'}}></div>
</div>
);
};
export default MapComponent;
Result
文本"Area: 303102.35 square meters"表示
这意味着您查询的建筑物或要素覆盖的总面积约为303,102.35平方米.这是一个定量的测量这些建筑物占据了多少表面积.
Zoom in for seeing detail polygon
Update Component Two different color building drawing
CulateAndDisplayArea函数判断每个功能的建筑标记,并为"办公"建筑应用蓝色,为"工业"建筑应用红色.
import React, { useState, useEffect, useRef, useCallback } from 'react';
import axios from 'axios';
import L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import * as turf from '@turf/turf';
const MapComponent = () => {
const [buildingData, setBuildingData] = useState(null);
const [area, setArea] = useState(0);
const mapRef = useRef(null);
// Initialize the map
useEffect(() => {
if (!mapRef.current) {
mapRef.current = L.map('map').setView([59.132659900251944, 9.727169813491393], 13); // Centered on Paris
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
}).addTo(mapRef.current);
}
}, []);
// Fetch building data
useEffect(() => {
const fetchData = async () => {
try {
const query = `[out:json];
(
way["building"="office"](around:3000,59.132659900251944, 9.727169813491393);
way["building"="industrial"](around:3000,59.132659900251944, 9.727169813491393);
);
out body; >; out skel qt;`;
const response = await axios.post(
'https://overpass-api.de/api/interpreter', query, {
headers: { 'Content-Type': 'text/plain' }
}
);
setBuildingData(response.data);
} catch (error) {
console.error('Error fetching data:', error);
}
};
fetchData();
}, []);
const calculateAndDisplayArea = useCallback(() => {
if (buildingData && mapRef.current) {
let totalArea = 0;
const nodeMapping = {}; // Assuming you have this mapping from node ID to { lat, lon }
buildingData.elements.forEach(element => {
if (element.type === 'node') {
nodeMapping[element.id] = { lat: element.lat, lon: element.lon };
}
});
const features = buildingData.elements.filter(element => element.type === 'way');
features.forEach(feature => {
if (feature.nodes && feature.nodes.length > 0) {
const coordinates = feature.nodes.map(nodeId => {
const node = nodeMapping[nodeId];
return [node.lat, node.lon];
});
if (coordinates.length > 0) {
// Check building type and apply color
const buildingType = feature.tags?.building;
const color = buildingType === 'office' ? 'blue' : buildingType === 'industrial' ? 'red' : 'grey';
L.polygon(coordinates, { color }).addTo(mapRef.current); // Apply color to polygon
const geoJsonPolygon = {
type: 'Polygon',
coordinates: [coordinates.map(coord => [coord[1], coord[0]])], // Convert to [lon, lat]
};
totalArea += turf.area(geoJsonPolygon);
}
}
});
setArea(totalArea);
}
}, [buildingData]);
useEffect(() => {
calculateAndDisplayArea();
}, [calculateAndDisplayArea, buildingData]);
return (
<div>
<p>Area: {area.toFixed(2)} square meters</p>
<div id="map" style={{ height: '800px', width: '1000px', margin: '0 auto'}}></div>
</div>
);
};
export default MapComponent;
Result