【echarts地圖製做】下鑽到鄉鎮/街道級別的

需求

展現西安市各區縣的地圖,點擊各區縣下鑽到各鄉鎮/街道,只能內網環境使用,不可用經過百度/高德地圖來實現。html

解決

利用地圖數據生成區域的geojson

網絡上大部分地圖數據只是到省市,最多到區縣,再往下的數據就比較難找了;通過搜索,找到了一個能夠買地圖數據的地方,數據能夠精確到鄉鎮/街道,價格還比較划算;ios

clipboard.png
地圖數據格式爲shp(shape格式),若是須要其餘的格式,得加點錢獲取好比svg、dbf、shx等額外格式的文件;
echarts支持的格式有geojson,此時咱們須要一個工具把shp格式的文件轉換爲geojson格式,推薦2種工具:json

這個工具是收費,每個月最多能夠轉換3次文件,上傳時網站會提示:axios

Don't forgot to upload all relevant files to your .SHP file - you need at least also .DXF and .SHX files uploaded together with your .SHP file!

不只要上傳shp格式,還要上傳dbf和shx等格式的文件,來得到更完整的地理數據,若是把全部格式的數據都上傳了,那麼生成的geojson可能會有問題(親測),因此只上傳3種格式是比較穩妥的辦法;瀏覽器

clipboard.png

上傳後會跳轉到一個設置的界面,先不要點擊開始轉換按鈕,首先檢查一下轉換的編碼格式,默認爲UTF-8,若是是中文的地圖數據,最好把轉換格式切換爲GB18030-Chinese格式;而後點擊開始轉換就能夠了。緩存

clipboard.png

轉換超過3個會提示下圖,這時能夠清一下瀏覽器緩存試試:網絡

clipboard.png

轉換後能夠下載到.geojson格式的數據文件,放到項目中時,把.geojson格式手動修改成.json格式,就能夠被echarts使用了,直接import geojson格式的文件會報錯;app

同時上傳.dbf .shp .shx .prj格式的文件,而後點擊右上角的export,就會看到以下界面,選擇geoJSON,就完成了。echarts

clipboard.png

利用geojson展現自定義的echart地圖

關於具體如何導入json格式數據到echarts的方法,能夠參考官方示例
如下是我本身的代碼:svg

<template>
    <div class="map-chart-wrapper"  ref="myEchart"
        :style="{height:height,width:width, left: mapPosition.left, top: mapPosition.top}">
    </div>
    <!-- '新城區': '&#9312;',
    '碑林區': '&#9313;',
    '蓮湖區': '&#9314;', -->
</template>
<script>
import echarts from 'echarts';
import axios from 'axios';
import 'echarts/theme/macarons.js';
import xianshi from '../common/json/xiaan.json'
import zhouzhixian from '../common/json/zhouzhi-cn.json'

const cityMap = {
    '西安市': xianshi,
    '周至縣': zhouzhixian,
}
const cityStyleMap = {
    '西安市': {
        position: {
            left: '-112px',
            top: '0px',
        },
        series: {
            left: 0,
            right: 0,
            top: '56px',
            bottom: '55px',
        }
    },
    '周至縣':  {
        position: {
            left: '-113px',
            top: '17px',
        },
        series: {
            left: 0,
            right: 0,
            top: '30px',
            bottom: '0px',
        }
    },
}
export default {
    props: {
        width: {
            type: String,
            default: '890px'
        },
        height: {
            type: String,
            default: '517px'
        },
        chartConfig:{
            type: Object,
            default: ()=>({
                title: null,
                backgroundColor: '#6a7985',
                seriesData: [],
                legendData: null,
                xAxisData: null,
                yAxisData: null,
                grid: {}
            }),
        },
        mapData:{
            type: Object,
            default: ()=>({}),
        },

    },
    data() {
        return {
            propsNew: '周至縣',
            chart: null,
            mapName: '',
            mapPosition: {
                left: '-117px',
                top: '36px'
            },
            areaGeoMap: {},
            districtList: [
                { label: '周至縣', value: '周至縣', class: 'zhouzhixian', code: "610124000000"},
                { label: '鄠邑區', value: '鄠邑區', class: 'huxian', code: "610118000000"},
                { label: '長安區', value: '長安區', class: 'changan', code: "610116000000"},
                { label: '雁塔區', value: '雁塔區', class: 'yanta', code: "610113000000"},
                { label: '未央區', value: '未央區', class: 'weiyang', code: "610112000000"},
                { label: '\u2460', value: '新城區', class: 'xincheng', code: "610102000000"},
                { label: '\u2461', value: '碑林區', class: 'beilin', code: "610103000000"},
                { label: '\u2462', value: '蓮湖區', class: 'lianhu', code: "610104000000"},
                { label: '灞橋區', value: '灞橋區', class: 'baqiao', code: "610111000000"},
                { label: '高陵區', value: '高陵區', class: 'gaoling', code: "610117000000"},
                { label: '臨潼區', value: '臨潼區', class: 'lintong', code: "610115000000"},
                { label: '閻良區', value: '閻良區', class: 'yanliang', code: "610114000000"},
                { label: '藍田縣', value: '藍田縣', class: 'lantian', code: "610122000000"},
            ],
        };
    },
    mounted() {
        this.createChart();
        this.registerMap('西安市')
    },
    beforeDestroy() {
        this.destroyChart();
    },
    watch: {
        chartConfig() {
            this.destroyChart();
            this.initChart();
        },
    },
    methods: {
        registerMap(name) { // 註冊地圖
            axios.get(cityMap[name]).then((response) => {
                const geoJson = response.data
                console.log(geoJson)
                this.areaGeoMap = geoJson.features.reduce((acc, item) => {
                    acc[item.properties.name] = item.properties.cp
                    return acc
                }, {})
                echarts.registerMap(name, geoJson);
                this.mapName = name;
                this.initChart()
            }).catch((error) => {
                alert('地圖數據未找到'+ error)
            })
        },
        createChart() {
            this.chart = echarts.init(this.$refs.myEchart, 'macarons');
            window.addEventListener("resize", this.chart.resize);
        },
        initChart() {
            // 清空當前實例,從而清空事件
            this.chart.clear()
            // this.chart.off('click', this.areaClick)
            let titleSubtext = '';
            let mapDown = true;
            if (this.mapName === '西安市') {
                mapDown = false
                titleSubtext = '\u2460' + ' 新城區\n' +
                                '\u2461' +' 碑林區\n' + 
                                '\u2462'+ ' 蓮湖區\n';
            }
            let styleData = cityStyleMap[this.mapName]
            this.mapPosition = styleData.position
            let seriesPos = styleData.series
            this.$emit('mapChange', {
                    mapDown,
                    name: this.mapName
                })
            var levelColorMap = {
                '1': 'rgba(241, 109, 115, .8)',
                '2': 'rgba(255, 235, 59, .7)',
                '3': 'rgba(147, 235, 248, 1)'
            };
            var COLORS = ["#070093", "#1c3fbf", "#1482e5", "#70b4eb", "#b4e0f3", "#ffffff"];
            
            // 閃動點的數據
            // const blinkDot = this.areaGeoMap[this.propsNew].concat(100)
            // console.log(blinkDot)
            // 把配置和數據放這裏
            const transparentMap = 0
            this.chart.setOption({
                title: {
                    text: '',
                    subtext: titleSubtext,
                    subtextStyle: {
                        color: '#d7d7d7',
                        fontSize: 14,
                        lineHeight: 80,
                        fontFamily: "Microsoft YaHei Light"
                    },
                    left: '320px',
                    top: '65px',
                },
                tooltip: {
                    trigger: 'item',
                    formatter: (data) => {
                        let key = data.name
                        if (key === '\u2460') {
                            key = '新城區'
                        }else if (key === '\u2461') {
                            key = '碑林區'
                        }else if (key === '\u2462') {
                            key = '蓮湖區'
                        }
                        return this.mapData[key] || key
                    } 
                },
                series: [
                    {
                        name: '',
                        type: 'map',
                        map: this.mapName,
                        left: seriesPos.left,
                        right: seriesPos.right,
                        top: seriesPos.top,
                        bottom: seriesPos.bottom,
                        selectedMode : 'single',
                        label: {
                            normal: {
                                fontSize: 14,
                                color: '#d7d7d7',
                                show: true,
                                fontFamily: "Microsoft YaHei Light"
                            },
                            emphasis: {
                                show: true
                            }
                        },
                        itemStyle: {
                            normal: {
                                color: function(params){
                                    return levelColorMap[params.value[3]];
                                },
                                // shadowOffsetX:5,
                                // shadowOffsetY:5,
                                // shadowBlur: 5,
                                // shadowColor: 'rgba(255,255,255,0.5)',
                                areaColor: 'rgba(255,255,255,0)',
                                borderColor: new echarts.graphic.RadialGradient(0.3, 0.3, 0.8, [{
                                                offset: 0,
                                                color: 'rgba(13,1,255,0)'
                                            }, {
                                                offset: 1,
                                                color: 'rgba(0,246,255,0)'
                                            }])
                            },
                            emphasis: {
                                areaColor: 'rgba(0,246,255,0.2)',
                                borderWidth: 0,
                                label: {
                                    color: "#fff",
                                }
                            }
                        },
                        data:[
                        
                        ],
                        nameMap: { // unicode 來源: http://xahlee.info/comp/unicode_circled_numbers.html
                            '新城區': '\u2460',
                            '碑林區': '\u2461',
                            '蓮湖區': '\u2462',
                        }
                    },
                    {
                        type: 'effectScatter',
                        coordinateSystem: 'geo',
                        // symbol: 'diamond',
                        // showEffectOn: 'render',
                        rippleEffect: {
                            period: 15,
                            scale: 6,
                            brushType: 'fill'
                        },
                        geoIndex: 0,
                        hoverAnimation: true,
                        itemStyle: {
                            normal: {
                                color: 'rgba(56,196,217,1)',
                                shadowBlur: 10,
                                shadowColor: '#fff'
                            }
                        },
                        data: []
                    }
                ]  
            });
            this.chart.on('click', this.areaClick)
        },
        destroyChart() {
            if (this.chart) {
                window.removeEventListener("resize", this.chart.resize);
                this.chart.dispose();
                this.chart = null;
            }
        },
        refreshData(areacode = false) {
            const params = {
                handleBack: (data) => {
                }
            }
            if (areacode) {
                params.area_code = areacode;
            }
            this.$store.dispatch('summaryData', params);
            this.$store.dispatch('rateCredit', params);
        },
        // 地圖的某塊區域點擊, @name參數爲地區名稱
        areaClick(params) {
            console.log(params)
            const name = params.name
            const selected = params.data.selected
            if (selected) {
                if (name === '周至縣') {
                    this.registerMap(name)
                }
                const areaObject = this.districtList.find((area) => {
                    return area.value === name
                })
                if (areaObject) {
                    this.refreshData(areaObject.code)
                }
            }
            else {
                this.refreshData()
            }
        }
    }
}
</script>
<style scoped>
.map-chart-wrapper{
    z-index: 9;
    position: absolute;
}
</style>

結果

設計圖的地圖效果是3D的,爲了達到效果,將地圖的顏色設爲透明,使用設計圖做爲背景圖,此時須要調整echart地圖的比例(top/bottom/right/left),調整好以後,地圖選擇高亮和點擊事件,和地區名字仍是繼續用echart實現。最終結果:

clipboard.png

參考文章

相關文章
相關標籤/搜索