echarts渲染地圖統(tǒng)計(jì)

一. 地圖數(shù)據(jù)獲取

- 全國及省市地圖可以直接在[阿里云數(shù)據(jù)可視化平臺](https://datav.aliyun.com/portal/school/atlas/area_selector)獲取
- 工業(yè)園/學(xué)校等自定義地圖可以在數(shù)據(jù)編輯器模塊自己繪制, 并導(dǎo)出GeoJSON地圖數(shù)據(jù)

二. 地圖注冊

- 1. 地圖JSON數(shù)據(jù)保存到j(luò)s文件
```
    export const xiangaoxin = {...}
```
- 2. 地圖注冊
    - 全國及省市地圖可以直接注冊到echarts
    ```
    import { chinaData } from '@/assets/js/china.js';
    import * as echarts from "echarts";
    
    // 注冊中國地圖
    echarts.registerMap('china', chinaData);
    ```
    - 自制地圖只注冊面數(shù)據(jù), 點(diǎn)和線通過后期echarts渲染添加
    ```
            import { xiangaoxin } from '@/assets/js/xiangaoxin.js';
    import * as echarts from "echarts";
            // 拆分面數(shù)據(jù)
    const polygonsData = transformedGeoJSON.features
        .filter(f => f.geometry.type === 'Polygon').map(p => {
        return {
            "type": "Feature",
            "properties": { "name": "北京" },
            "geometry": {
                "type": "Polygon",
                "coordinates": p.geometry.coordinates
            }
        };
    });
            // 注冊園區(qū)地圖
    echarts.registerMap('xiangaoxin1', {
        "type": "FeatureCollection",
        "features": polygonsData
    });
    ```

三. 地圖渲染完整代碼如下

```
<template>
    <div class="content-container" :style="{ backgroundImage: `url(${DashboardBg})` }">
        <div ref="mapChartRef" style="width: calc(100% - 15px); height: calc(100vh - 15px);">
        </div>
    </div>
    </template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from 'vue';
import * as echarts from "echarts";
    import { getVisitorMapStatsInfo } from '@/services/statsService'; 
import DashboardBg from '@/assets/img/dashboard/bg.jpg';
import { xiangaoxin1 } from '@/assets/js/xiangaoxin1.js';
    import { gcj02towgs84 } from 'coordtransform';
    
    /**
 * 園區(qū)中心點(diǎn)經(jīng)緯度
 * 各個門崗點(diǎn)加字段
 *  RegionId
 *  RegionName
 */
    // 地圖綁定對象
let mapChartObj = null;
// 點(diǎn)位數(shù)據(jù)
let pointData = null;
// 線條數(shù)據(jù)
let lineData = null;
// 面數(shù)據(jù)
let polygonsData = null;
// 圖表依賴元素
const mapChartRef = ref();

    onMounted(() => {
    // 監(jiān)聽窗口大小變化,自適應(yīng)調(diào)整圖表
    window.addEventListener('resize', () => {
        if (mapChartObj) {
            mapChartObj.resize();
        }
    });
            
            // 地圖數(shù)據(jù)初始化
    mapDataInit();

    // 注冊園區(qū)地圖
    echarts.registerMap('xiangaoxin1', {
        "type": "FeatureCollection",
        "features": polygonsData
    });

            // 圖表渲染
    renderChart();
});
    // 地圖數(shù)據(jù)初始化
const mapDataInit = () => {
    const transformedGeoJSON = JSON.parse(JSON.stringify(xiangaoxin1));
    transformedGeoJSON.features.forEach(feature => {
        feature.geometry.coordinates = transformCoordinates(feature.geometry.coordinates);
    });
            
            // 地圖點(diǎn)位
    pointData = transformedGeoJSON.features
        .filter(f => f.geometry.type === 'Point').map(f => {
            return {
                name: f.properties.ElementName,
                value: f.geometry.coordinates, // [經(jīng)度, 緯度]
            }
        });
          
            // 地圖線條
    lineData = transformedGeoJSON.features
        .filter(f => f.geometry.type === 'LineString').map(feature => {
            return {
                                    name: feature.properties.name,
                coords: feature.geometry.coordinates, // 線的坐標(biāo)數(shù)組
                lineStyle: {
                    width: 5, // 線寬
                    color: '#3C9BE5',
                    opacity: 0.8
                },
                                    // 可根據(jù)屬性設(shè)置線的視覺效果
                effect: {
                    show: true,
                    symbol: 'arrow',
                    symbolSize: 6,
                    trailLength: 0.5
                }
            }
        });
    // 地圖面
    polygonsData = transformedGeoJSON.features
        .filter(f => f.geometry.type === 'Polygon').map(p => {
        return {
            "type": "Feature",
            "properties": { "name": "北京" },
            "geometry": {
                "type": "Polygon",
                "coordinates": p.geometry.coordinates
            }
        };
    });
};

    // 遞歸轉(zhuǎn)換GeoJSON中的所有坐標(biāo)
const transformCoordinates = (coords) => {
    if (Array.isArray(coords[0])) {
        return coords.map(coord => transformCoordinates(coord));
    } else {
        // coords格式:[經(jīng)度, 緯度]
        const [lon, lat] = gcj02towgs84(coords[0], coords[1]);
        return [lon, lat];
    }
}

    const renderChart = () => {
    setTimeout(() => {
        if (!mapChartObj) {
            mapChartObj = echarts.init(mapChartRef.value);
            mapChartObj.on('click', function (param) {
                console.log(param);
                if (param.componentType == 'series' &&
                    param.componentSubType == 'effectScatter') {
                    console.log(param.data.name);
                    console.log(param.data.value);
                }
            });
        
            let option = getOption();
            mapChartObj.setOption(option);
            setMapData();
        }
    }, 50);
}

    const getOption = () => {
    // 平面地圖配置
    // let option = {
    //     visualMap: {
    //         type: "piecewise",
    //         show: false,
    //         min: 0,
    //         max: 1000000,
    //         left: "28%",
    //         bottom: "25%",
    //         showLabel: true,
    //         textStyle: {
    //             color: "#AAAAAA",
    //         },
    //     },
    //     geo: {
    //         map: "xiangaoxin1",
    //         // 默認(rèn)縮放比
    //         zoom: 0.8,
    //         top: "30%",
    //         // 縮放拖拽
    //         roam: true,
    //         scaleLimit: {
    //             min: 0.8, // 最小縮放比例(0.5倍)
    //             max: 1  // 最大縮放比例(3倍)
    //         },
    //         label: {
    //             // 正常情況是否顯示
    //             normal: {
    //                 show: false,
    //                 fontSize: "14",
    //                 color: "#00D9A9",
    //             },
    //             // 鼠標(biāo)懸停是否顯示
    //             emphasis: {
    //                 show: false
    //             }
    //         },
    //         // 設(shè)置視角中心點(diǎn)
    //         center: [108.841, 34.175],
    //         // 設(shè)置地圖樣式
    //         itemStyle: {
    //             // 地圖區(qū)域顏色
    //             areaColor: '#00254C',
    //             // 分界線顏色
    //             borderColor: '#00B0C4',
    //             borderWidth: '2',
    //             emphasis: {
    //                 areaColor: '#006A83',
    //             }
    //         }
    //     },
    //     series: [
    //         {
    //             // 有擴(kuò)散效果的散點(diǎn)圖
    //             type: 'scatter',
    //             coordinateSystem: 'geo',
    //             // 標(biāo)記位置, value 前兩個值為經(jīng)緯度, 第三個值為渲染值
    //             data: [
    //                 { name: '東門', value: [108.8458, 34.1806, 300] }
    //             ],
    //             // data: pointData,
    //             // 小紅旗
    //             symbol: "image://data:image/png;base64,iVBOR...EdkKMAAAAASUVORK5CYII=",
            //             symbolSize: (value, params) => {
    //                 // console.log(value);
    //                 return 30; // 根據(jù)第三個數(shù)值調(diào)整尺寸
    //             },
    //             // 標(biāo)記label顏色
    //             itemStyle: { color: '#FFFFFF' },
    //             label: {
    //                 // 直接顯示
    //                 show: true,
    //                 position: 'top',
    //                 formatter: function(params) {
    //                     // 自定義顯示內(nèi)容,例如顯示名稱和坐標(biāo)值
    //                     return `${params.name}\n設(shè)備數(shù) ${params.value[2]}`;
    //                 },
    //                 // 鼠標(biāo)懸浮顯示
    //                 emphasis: {
    //                     show: true
    //                 },
    //                 color: '#67DDFF'
    //             }
    //         }
    //     ],
    // };
    const option = {
        // 3D 地圖配置
        geo3D: {
            show: true,
            map: 'xiangaoxin1', // 'xiangaoxin1',
            // 調(diào)整地圖顯示角度和大小
            boxWidth: 60,
            // 整個3D盒子高度
            boxHeight: 15,
            boxDepth: 80,
            // 地圖區(qū)域高度
            regionHeight: 2,
            // ### environment 1 環(huán)境光('auto' 自動適應(yīng))
            environment: 'auto',
            instancing: false,
            // 三維地理坐標(biāo)系組件 中三維圖形的視覺屬性,包括顏色,透明度,描邊等
            itemStyle: {
                color: '#00254C',
                opacity: 0.3,
                borderWidth: 1,
                borderColor: '#00B0C4',
            },
            viewControl: {
                autoRotate: false, // 自動旋轉(zhuǎn)
                rotateSensitivity: 1, // 旋轉(zhuǎn)靈敏度
                zoomSensitivity: 0, // 縮放靈敏度
                panSensitivity: 0,
                projection: 'perspective',
                distance: 180,
                alpha: 45,
                beta: 3,
                minDistance: 80,
                maxDistance: 120,
                minAlpha: -100,
                maxAlpha: 100,
                minBeta: -100,
                maxBeta: 100
            },
            emphasis: {
                label: {
                    show: false,
                    fontSize: "12",
                    distance: 10,
                    color: "#00254C",
                    textStyle: {
                        borderWidth: 1,
                        borderColor: '#000000',
                        fontSize: 12,
                        // normal bold bolder lighter
                        fontWeight: 'normal'
                    }
                },
                itemStyle: {
                    color: '#006A83',
                    opacity: 0.3
                }
            },
            shading: 'lambert',
        },
        // 3D線條
        series: [{
            type: 'lines3D',            // 3D線條類型
            coordinateSystem: 'geo3D',  // 關(guān)聯(lián)3D地理坐標(biāo)系
            polyline: true,             // 是否為直線
            data: lineData,             // 線條數(shù)據(jù)
            // 線條樣式
            lineStyle: {
                width: 4,
                color: '#469EF7',
                opacity: 1
            },
            // 線條特效
            // effect: {
            //     show: true,
            //     symbol: 'circle',
            //     symbolSize: 6,
            //     period: 3,
            //     trailLength: 0.4
            // },
            // 鼠標(biāo)交互
            emphasis: {
                lineStyle: {
                    width: 5,
                    color: '#00B0C4'
                }
            }
        // 3D點(diǎn)位
        }, {
            type: 'scatter3D',          // 3D點(diǎn)類型
            coordinateSystem: 'geo3D',  // 關(guān)聯(lián)3D地理坐標(biāo)系
            data: pointData,            // 點(diǎn)數(shù)據(jù)
            // 點(diǎn)的樣式
            symbol: 'circle',           // 點(diǎn)形狀(circle, diamond, triangle等)
            symbolSize: 12,             // 基礎(chǔ)大小(會被數(shù)據(jù)中的symbolSize覆蓋)
            // 點(diǎn)的顏色映射(也可通過itemStyle單獨(dú)設(shè)置)
            colorBy: 'data',
            itemStyle: {
                color: '#10FCB0',
                // borderWidth: '0.1',
                // borderColor: '#FFFFFF'
            },
            // 鼠標(biāo)交互效果
            emphasis: {
                itemStyle: {
                    color: '#FFCC00',
                    shadowBlur: 10
                },
                scale: true  // 懸停時放大
            },
            label: {
                show: true,
                formatter: ''
            },
            // 點(diǎn)的動畫效果
            animationDurationUpdate: 1000,
            animationEasingUpdate: 1000,
            animationEasing: 'elasticOut',
            // 閃爍配置
            blink: {
                enable: true,
                speed: 500,                      // 閃爍周期(ms):快/慢
                minOpacity: 0.3,                 // 最小透明度
                maxOpacity: 1                    // 最大透明度
            }
        }]
    };
    return option;
}

 // 3. 計(jì)算地圖中心坐標(biāo)(用于定位)
 const getMapCenter = (geoJSON) => {
    let lonSum = 0, latSum = 0, count = 0;
    
    function collectCoords(coords) {
        if (typeof coords[0] === 'number') {
            lonSum += coords[0];
            latSum += coords[1];
            count++;
        } else {
            coords.forEach(coord => collectCoords(coord));
        }
    }
    
    geoJSON.features.forEach(feature => {
        collectCoords(feature.geometry.coordinates);
    });
    
    return [lonSum / count, latSum / count];
}

// 設(shè)置地圖數(shù)據(jù)
const setMapData = () => {
    // getVisitorMapStatsInfo({}, (result: ResultModel) => {
    //     const dataList = result.Data.map((item) => {
    //         return { 
    //             name: item.WorkPlacename, 
    //             value: [item.Longitude, item.Latitude, item.Amount] 
    //         };
    //     });
    //     if (mapChartObj) {
    //         mapChartObj.setOption({
    //             series: [{
    //                 data: dataList
    //             }]
    //         });
    //     }
    // });
};

// 組件卸載時銷毀圖表
onUnmounted(() => {
    if (mapChartObj) {
        mapChartObj.dispose();
        mapChartObj = null;
    }
});

onUnmounted(() => {
    clearInterval(intervalId);
});

defineExpose({
    renderChart
});
</script>
<style lang="less" scoped>
.content-container {
    min-width: 1450;
    height: 100vh;
    background-color: #FFFFFF;
    position: relative;
    .map {
        position: absolute;
        z-index: 1;
    }
    .l1 {
        position: absolute;
        z-index: 2;
        top: 20px;
        left: 20px;
    }
    .r1 {
        position: absolute;
        z-index: 2;
        top: 20px;
        right: 20px;
    }
}
.global-tabs {
    ::v-deep(.el-tabs__nav-scroll) {
        padding: 20px 0 0 20px;
    }
    ::v-deep(.el-tabs__item) {
        // --el-font-size-base: 16px;
        font-weight: 600;
    }
}
::v-deep(.el-tabs__nav-wrap:after) {
    background: none;
}
::v-deep(.el-tabs__item.is-active, .el-tabs__item:hover) {
    color: #00CEFF;
}
::v-deep(.el-tabs__item) {
    color: #0095B8;
}
::v-deep(.el-tabs__nav) {
    padding-left: 10px;
}
</style>
```
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容