| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- <template>
- <div class="map-wrapper">
- <div ref="mapContainer" class="map-container"></div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted } from 'vue';
- import L from 'leaflet';
- import 'leaflet/dist/leaflet.css';
- const mapContainer = ref(null);
- // 定义蓝色三角形标记(保持不变)
- const blueTriangle = L.divIcon({
- className: 'custom-div-icon',
- html: `<svg width="24" height="24" viewBox="0 0 24 24">
- <path d="M12 2L2 22h20L12 2z" fill="#0066CC" stroke="#003366" stroke-width="2"/>
- </svg>`,
- iconSize: [24, 24],
- iconAnchor: [12, 24]
- });
- onMounted(() => {
- if (!mapContainer.value) {
- console.error('❌ 地图容器未找到!');
- return;
- }
- const map = L.map(mapContainer.value, {
- center: [24.7, 114], // 韶关大致中心
- zoom: 8.5,
- minZoom: 8.3,
- });
- // 区县颜色映射(保持不变)
- const districtColorMap = {
- "武江区": "#FF6B6B",
- "浈江区": "#4ECDC4",
- "曲江区": "#FFD166",
- "始兴县": "#A0DAA9",
- "仁化县": "#6A0572",
- "翁源县": "#1A535C",
- "乳源瑶族自治县": "#FF9F1C",
- "新丰县": "#87CEEB",
- "乐昌市": "#118AB2",
- "南雄市": "#06D6A0",
- "韶关市": "#cccccc",
- };
- // 区县颜色匹配函数(保持不变)
- function getDistrictColor(name) {
- if (districtColorMap[name]) return districtColorMap[name];
- const normalizedName = name.replace(/市|县|区|自治县/g, '');
- for (const key in districtColorMap) {
- if (key.includes(normalizedName) || normalizedName.includes(key.replace(/市|县|区|自治县/g, ''))) {
- return districtColorMap[key];
- }
- }
- return '#cccccc';
- }
- // 加载区县边界(保持不变)
- fetch('/data/韶关市各区县边界图.geojson')
- .then(res => {
- if (!res.ok) throw new Error(`区县边界加载失败:${res.status}`);
- return res.json();
- })
- .then(geojson => {
- L.geoJSON(geojson, {
- style: (feature) => ({
- fillColor: getDistrictColor(feature.properties.name || ''),
- fillOpacity: 0.7,
- color: '#333333',
- weight: 2,
- }),
- }).addTo(map);
- // 从接口加载大气污染源数据(核心修改:适配新接口)
- fetch('http://localhost:3000/table/Atmosphere_company_data')
- .then(res => {
- if (!res.ok) throw new Error(`接口请求失败:${res.status}`);
- return res.json();
- })
- .then(apiData => {
- console.log('✅ 接口数据加载完成,共', apiData.length, '条记录');
-
- let markerCount = 0;
- apiData.forEach((item, idx) => {
- try {
- // 解析经纬度(注意:接口里经纬度是字符串,需转数字)
- const lng = parseFloat(item.经度);
- const lat = parseFloat(item.纬度);
- if (isNaN(lat) || isNaN(lng) || lat < 22.7 || lat > 25.5 || lng < 112.7 || lng > 115.3) {
- console.warn(`❌ 无效坐标(第${idx}条):`, lat, lng);
- return;
- }
- // 解析大气颗粒物排放量
- const emission = parseFloat(item["大气颗粒物排放(t/a)"]);
- const formattedEmission = isNaN(emission)
- ? '未知'
- : `${emission.toFixed(3)} t/a`;
- // 创建标记(保持不变)
- const marker = L.marker([lat, lng], {
- icon: blueTriangle,
- zIndexOffset: 1000,
- }).addTo(map);
- // 弹窗内容修改:适配新字段
- marker.bindPopup(`
- <div class="popup-container">
- <h3 class="popup-title">${item.公司 || '未知'}</h3>
- <div class="popup-divider"></div>
- <p><strong>污染源序号:</strong> ${item["污染源序号"] || '未知'}</p>
- <p><strong>企业类型:</strong> ${item.类型 || '未知'}</p>
- <p><strong>所属区县:</strong> ${item["所属区县"] || '未知'}</p>
- <p><strong>大气颗粒物排放:</strong> ${formattedEmission}</p>
- </div>
- `);
- markerCount++;
- } catch (err) {
- console.error(`❌ 处理第${idx}条数据失败:`, err);
- }
- });
- console.log(`✅ 成功创建 ${markerCount} 个有效标记`);
- })
- .catch(err => {
- console.error('❌ 接口数据加载失败:', err);
- alert('数据加载错误:' + err.message);
- });
- })
- .catch(err => {
- console.error('❌ 区县边界加载失败:', err);
- alert('区县边界加载错误:' + err.message);
- });
- map.on('load', () => {
- // 延迟执行,确保 DOM 已完全渲染
- setTimeout(() => {
- map.invalidateSize(); // 强制 Leaflet 重新计算地图尺寸
- console.log('✅ 地图尺寸已重新计算');
- }, 300);
- });
- // 监听窗口大小变化,确保响应式布局中地图尺寸正确
- window.addEventListener('resize', () => {
- map.invalidateSize();
- });
- });
- </script>
- <style scoped>
- .map-wrapper {
- width: 100%;
- height: 100%;
- position: relative;
- }
- .map-container {
- width: 100% !important;
- height: 100% !important;
- }
- /* 弹窗样式 */
- ::v-deep .popup-title {
- text-align: center;
- font-size: 18px;
- font-weight: 700;
- color: #0066CC;
- margin: 0 0 6px;
- border-bottom: none;
- padding-bottom: 8px;
- }
- ::v-deep .popup-divider {
- height: 1px;
- background: #0066CC;
- margin: 8px 0;
- }
- ::v-deep .popup-container {
- min-width: 240px;
- max-width: 300px;
- padding: 16px;
- font-family: "Microsoft YaHei", sans-serif;
- }
- ::v-deep .popup-container p {
- margin: 6px 0;
- font-size: 15px;
- color: #666;
- line-height: 1.6;
- }
- ::v-deep .popup-container strong {
- color: #0066CC;
- font-weight: 600;
- }
- ::v-deep .exceeding {
- color: #FF3333;
- font-weight: bold;
- }
- /* 美化弹窗 */
- ::v-deep .leaflet-popup-content-wrapper {
- padding: 0 !important;
- border-radius: 12px !important;
- box-shadow: 0 6px 16px rgba(0,0,0,0.2) !important;
- }
- ::v-deep .leaflet-popup-content {
- margin: 0 !important;
- width: auto !important;
- }
- ::v-deep .leaflet-popup-tip {
- display: none;
- }
- /* 图例样式 */
- ::v-deep .info {
- padding: 6px 8px;
- background: white;
- background: rgba(255,255,255,0.9);
- box-shadow: 0 0 15px rgba(0,0,0,0.2);
- border-radius: 5px;
- }
- /* 自定义标记样式 */
- ::v-deep .custom-div-icon svg {
- transition: transform 0.2s;
- display: block;
- }
- </style>
|