中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

介紹產(chǎn)品網(wǎng)站制作制作自己的網(wǎng)頁(yè)

介紹產(chǎn)品網(wǎng)站制作,制作自己的網(wǎng)頁(yè),手機(jī)域名注冊(cè)騙局案例,web網(wǎng)站在線支付等怎么做vue3echarts繪制某省區(qū)縣地圖 工作中經(jīng)常需要畫各種各樣的圖,echarts是使用最多的工具,接近春節(jié),想把之前畫的echarts圖做一個(gè)整合,方便同事和自己隨時(shí)使用,因此用vue3專門寫了個(gè)web項(xiàng)目,考慮之后不斷完善…

vue3+echarts繪制某省區(qū)縣地圖

工作中經(jīng)常需要畫各種各樣的圖,echarts是使用最多的工具,接近春節(jié),想把之前畫的echarts圖做一個(gè)整合,方便同事和自己隨時(shí)使用,因此用vue3專門寫了個(gè)web項(xiàng)目,考慮之后不斷完善

其中有這么個(gè)需求,需要展示某省各區(qū)縣的數(shù)據(jù),寫在vue3項(xiàng)目中,最終展示結(jié)果如下:

image-20240125173609220

大體的思路如下:

  1. 在阿里云dataV數(shù)據(jù)可視化平臺(tái)獲取數(shù)據(jù)
  2. 整合某省各區(qū)縣的數(shù)據(jù)成為一個(gè)單獨(dú)的文件
  3. echarts中注冊(cè)這個(gè)省的地圖
  4. echarts畫圖

主要用的程序語(yǔ)言是JavaScript和Python

下面詳細(xì)介紹,有些技術(shù)細(xì)節(jié)也是自己經(jīng)常遇到的,通過(guò)這段時(shí)間強(qiáng)化訓(xùn)練,感覺(jué)對(duì)echarts越來(lái)越熟練了

一、阿里云dataV地圖數(shù)據(jù)獲取

首先上地址,阿里云數(shù)據(jù)可視化平臺(tái),感謝阿里和高德提供如此牛逼的工具

然后選擇點(diǎn)擊自己所需的省份,比如上面圖示的河北

image-20240125174337829

接下來(lái)依次點(diǎn)擊河北省各地級(jí)市,比如我點(diǎn)了石家莊,此時(shí)右側(cè)出現(xiàn)了一個(gè)json鏈接,如下圖,復(fù)制那個(gè)鏈接

image-20240125174601709

如果瀏覽器裝了解析json文件的插件,就會(huì)顯示這個(gè)json文件的數(shù)據(jù),如果安裝插件,應(yīng)該會(huì)直接把這個(gè)json文件下載下來(lái),json數(shù)據(jù)如下:

image-20240125174758844

接下來(lái),依次去點(diǎn)擊河北其他城市的地圖,并獲取數(shù)據(jù),也可以寫個(gè)爬蟲的程序,挺簡(jiǎn)單的

二、將各地市的數(shù)據(jù),整合成一個(gè)省的數(shù)據(jù)

其實(shí)思路就是把單個(gè)json中的features提取出來(lái),然后整合到一個(gè)json文件中去

把上一步下載好的所有文件放到一個(gè)目錄中,如folder

接下來(lái)用Python處理一下

    features = []  # 初始化 features 列表for file in os.listdir(folder):filename = os.path.join(folder, file)try:with open(filename, 'r', encoding='utf-8') as f:data = json.load(f)features.extend(data.get('features', []))except (IOError, json.JSONDecodeError) as e:print(f"Error reading JSON file {filename}: {e}")json_file = {"type": "FeatureCollection","features": features    }# 導(dǎo)出為 JSON 文件output_file_path = 'hebei_combined.json'with open(output_file_path, 'w', encoding='utf-8') as output_file:json.dump(json_file, output_file, ensure_ascii=False, indent=2)

通過(guò)處理后,得到的數(shù)據(jù)樣式如下:

image-20240125175455169

我不太喜歡在vue項(xiàng)目中直接使用json,因?yàn)楹芏嗲闆r下都需要異步引入,對(duì)于沒(méi)有后端的項(xiàng)目,寫起來(lái)比較費(fèi)勁。更為致命的是,echarts對(duì)各種異步的操作非常不友好,經(jīng)常在等待數(shù)據(jù)的時(shí)候,發(fā)現(xiàn)數(shù)據(jù)還沒(méi)有返回,就會(huì)各種報(bào)錯(cuò)。我更傾向于把數(shù)據(jù)寫入到j(luò)s文件中,然后對(duì)外暴露,實(shí)際上這個(gè)項(xiàng)目我也是這么操作的,我把json里的內(nèi)容放進(jìn)同名js文件中,然后按需向外暴露,對(duì)象名為hebeiAreas

三、echarts注冊(cè)地圖

echarts中注冊(cè)地圖非常簡(jiǎn)單,就兩步:

  1. 導(dǎo)入地圖數(shù)據(jù)
  2. 注冊(cè)

體現(xiàn)在程序中如下:

import * as echarts from "echarts";
import { hebeiAreas } from '@/assets/js/areasOfProvince/hebei_combined'
// 注冊(cè)
echarts.registerMap('proMap', hebeiAreas)

這里的注冊(cè)需要寫在正確的地方,如果只畫一個(gè)圖,寫在哪里都無(wú)所謂,如果涉及到多個(gè)省份的切換,我建議寫在切換成功的地方,或者是重繪地圖的地方

四、繪圖以及踏過(guò)的坑

繪圖就是正兒八經(jīng)寫代碼,我先上完整代碼

<template><div class="container"><div class="top"><el-select v-model="province" placeholder="請(qǐng)選擇省份" @change="choosePro" style="width: 120px"><el-option v-for="(item, index) in provinces" :key="index" :label="item.label":value="item.value"></el-option></el-select><el-button type="primary" style="margin-left: 10px;" @click="changeData">更換數(shù)據(jù)</el-button><input ref="input" type="file" style="display: none" @change="handleFileChange" /></div><div class="proMap" ref="proMap"></div></div>
</template><script setup>
import { ref, onMounted, h } from 'vue'
import { provinces } from './data/provinceName'
import { ElMessage, ElNotification } from 'element-plus'
import * as echarts from "echarts";
import { areas } from '@/assets/js/areas'
import { hebeiAreas } from '@/assets/js/areasOfProvince/hebei_combined'const province = ref('hebei')
const provinceZH = ref('河北')
const provinceCode = ref('13')
const proMap = ref()const drawData = ref([])
const maxData = ref(100)const getMaxData = () => {const arr = []arr.push(drawData.value.map(item => item.value))maxData.value = Math.max(...arr[0])
}const getData = () => {const areasOfCurrentProvince = areas.filter(item => item.provinceCode == provinceCode.value)areasOfCurrentProvince.forEach(item => {drawData.value.push({name: item.name,value: Math.floor(Math.random() * 101)})});getMaxData()
}// 更換省份
const choosePro = () => {console.log(province.value)if (province.value != 'hebei') {ElNotification({title: '提醒',message: h('i', { style: 'color: teal' }, '省份到區(qū)縣分塊需要處理大量數(shù)據(jù),功能待后期完成,現(xiàn)在只做了河北的'),duration: 0})province.value = 'hebei'}
}
// 更換數(shù)據(jù)
// 隱藏輸入框的dom
const input = ref()
const changeData = () => {ElNotification({title: '提醒',message: h('i', { style: 'color: teal' }, '請(qǐng)務(wù)必使用當(dāng)前省份下的區(qū)縣數(shù)據(jù),否則無(wú)法顯示正確的數(shù)據(jù)'),duration: 0})input.value.click()
}
const handleFileChange = async event => {const file = event.target.files[0]const reader = new FileReader()reader.readAsText(file, "UTF-8")reader.onload = async (evt) => {const fileString = await evt.target.resultconst count = fileString.trim().split('\n').lengthconsole.log(count)const handleData = []for (let i = 0; i < count; i++) {const fileline = fileString.split("\n")[i].split('\t')handleData.push({ name: fileline[0], value: parseInt(fileline[1]) })}// 更換數(shù)據(jù)drawData.value = handleDatagetMaxData()drawProMap()}
}
// 畫地圖相關(guān)
let initMap
const drawProMap = () => {echarts.registerMap('proMap', hebeiAreas)if (initMap != null && initMap != "" && initMap != undefined) {initMap.dispose(); //銷毀}initMap = echarts.init(proMap.value)initMap.setOption({backgroundColor: "transparent", // 設(shè)置背景色透明tooltip: {show: true,},visualMap: {text: ["", ""],showLabel: true,left: "200",bottom: "100",min: 0,max: maxData.value,inRange: {color: ["#edfbfb", "#b7d6f3", "#40a9ed", "#3598c1", "#215096"],},// splitNumber: 5,seriesIndex: "0",},series: [{type: "map",map: 'proMap',tooltip: {trigger: 'item',formatter: function (params) {// params 包含了鼠標(biāo)懸浮時(shí)的相關(guān)信息return params.name + '<br/>' + '數(shù)值: ' + params.value;}},zoom: 1,label: {show: false, // 顯示地市名稱color: "#000",align: "center",},top: "10%",left: "center",aspectScale: 0.75,roam: true, // 地圖縮放和平移itemStyle: {borderColor: "#3ad6ff", // 省分界線顏色  陰影效果的borderWidth: 1,areaColor: "#F5F5F5",opacity: 1,},// 控制鼠標(biāo)懸浮上去的效果emphasis: {// 聚焦后顏色disabled: false, // 開啟高亮label: {align: "center",color: "#ffffff",},itemStyle: {color: "#ffffff",areaColor: "#0075f4", // 陰影效果 鼠標(biāo)移動(dòng)上去的顏色},},z: 2,data: drawData.value,}]})window.addEventListener("resize", () => {initMap.resize();});
}onMounted(() => {getData()setTimeout(() => { drawProMap() }, 200)
})
</script><style lang="scss" scoped>
.top {padding: 5px;width: 100%;box-shadow: rgba(17, 17, 26, 0.1) 0px 0px 16px;
}.proMap {height: 95%;width: 95%;
}
</style>

以上代碼有自己踏過(guò)的不少坑,我都說(shuō)明一下,肯定還有其他坑,一句話,echarts全是坑

  1. getData()是生成地圖對(duì)應(yīng)數(shù)據(jù)的方法,我這里用了隨機(jī)數(shù),數(shù)據(jù)格式如下:

    [{name: '淶源縣', value: 100},....
    ]
    

    就是由key為name和value對(duì)象組成的數(shù)組

    getMaxData()是獲取上面數(shù)組中的value的最大值,這主要是繪圖的時(shí)候,圖例范圍的最大值設(shè)置

    drawProMap()是繪制地圖的方法

  2. 坑1:注意onMounted鉤子中的寫法:

    onMounted(() => {getData()setTimeout(() => { drawProMap() }, 200)
    })
    

    掛載組件之前,先要獲取數(shù)據(jù),然后組件出現(xiàn),就應(yīng)該有圖出現(xiàn),這里我設(shè)置了0.2s的延時(shí)畫圖,原因是需要先等dom渲染完成后再畫圖,不然會(huì)直接報(bào)錯(cuò)

  3. 坑2:畫圖dom的寬和高必須要先設(shè)置,看我的樣式:

    .proMap {height: 95%;width: 95%;
    }
    

    這必須寫,不然圖出不來(lái),還會(huì)報(bào)警說(shuō)無(wú)法獲取dom的寬高

  4. 坑3:地圖dom的初始化問(wèn)題:

    看相關(guān)的代碼

    // 畫地圖相關(guān)
    let initMap
    const drawProMap = () => {echarts.registerMap('proMap', hebeiAreas)if (initMap != null && initMap != "" && initMap != undefined) {initMap.dispose(); //銷毀}initMap = echarts.init(proMap.value)/*省略其他代碼*/
    }
    

    一般情況下,可能我們會(huì)在畫圖的時(shí)候,直接就是:

    const initMap = echarts.init(proMap.value)
    

    上來(lái)就直接初始化畫圖的dom,可能的情況是,如果是在相同的dom上重繪echarts圖,控制臺(tái)就會(huì)報(bào)警(并非報(bào)錯(cuò),效果會(huì)正常出現(xiàn)),說(shuō)這個(gè)dom上本來(lái)就存在echarts圖,所以在初始化之前,正確的操作是判斷dom上的echarts圖是否占用,占用的話,就銷毀,也就是initMap.dispose();

  5. 從上面的代碼可以看出,省份是可以選擇的,數(shù)據(jù)也是可以改的

    • 先說(shuō)改數(shù)據(jù)。改數(shù)據(jù)的邏輯是設(shè)定一個(gè)隱藏的input dom元素,為什么要用input,因?yàn)閕nput可以打開文件,如下代碼,其中type="file"就是打開文件,change是文件改變的事件

      <input ref="input" type="file" style="display: none" @change="handleFileChange" />
      

      由于這個(gè)dom是隱藏的(style="display: none"),所以打開文件應(yīng)該是由按鈕來(lái)控制,也就是下面這行代碼

      <el-button type="primary" style="margin-left: 10px;" @click="changeData">更換數(shù)據(jù)</el-button>
      

      它倆的邏輯關(guān)系是:

      • 點(diǎn)擊按鈕,隱藏的input按鈕實(shí)現(xiàn)點(diǎn)擊事件,如下代碼:

        const input = ref()
        const changeData = () => {ElNotification({title: '提醒',message: h('i', { style: 'color: teal' }, '請(qǐng)務(wù)必使用當(dāng)前省份下的區(qū)縣數(shù)據(jù),否則無(wú)法顯示正確的數(shù)據(jù)'),duration: 0})input.value.click()
        }
        
      • 接下來(lái)就會(huì)觸發(fā)input的文件打開功能,選定文件后,就會(huì)執(zhí)行handleFileChange方法,在這個(gè)方法中,使用了處理txt文本文件的方法,需要注意其中的異步操作,并且有處理?yè)Q行以及按tab分割的邏輯,這里需要根據(jù)個(gè)人的項(xiàng)目進(jìn)行適配,處理好數(shù)據(jù)后,替換畫圖的數(shù)據(jù)即可,然后執(zhí)行獲取最大值和畫圖方法,相關(guān)代碼如下:

        const handleFileChange = async event => {const file = event.target.files[0]const reader = new FileReader()reader.readAsText(file, "UTF-8")reader.onload = async (evt) => {const fileString = await evt.target.resultconst count = fileString.trim().split('\n').lengthconsole.log(count)const handleData = []for (let i = 0; i < count; i++) {const fileline = fileString.split("\n")[i].split('\t')handleData.push({ name: fileline[0], value: parseInt(fileline[1]) })}// 更換數(shù)據(jù)drawData.value = handleDatagetMaxData()drawProMap()}
        }
        
    • 再說(shuō)切換省份。我的代碼中并沒(méi)有實(shí)現(xiàn)切換省份的邏輯,因?yàn)樾枰罅康臄?shù)據(jù)支撐,也就是說(shuō)要把全國(guó)34個(gè)省級(jí)行政區(qū)劃(包括港澳臺(tái))的地圖文件都獲取,切換成功后,異步引入地圖文件,并注冊(cè)地圖,然后畫圖,這一步我在其他地方實(shí)現(xiàn)過(guò),同樣存在坑

      坑4:異步導(dǎo)入json文件,首次繪圖會(huì)出現(xiàn)報(bào)錯(cuò),報(bào)錯(cuò)如下:

      Error: Invalid geoJson format coordinate.charCodeAt is not a function

      但是刷新頁(yè)面就正常了,查了一下相關(guān)的資料,有人解釋是:

      因?yàn)?echarts 會(huì)繪制解析 json 之后 執(zhí)行 decode 方法 后 會(huì)將其 UTF8Encoding 的值 從 true 改為false,第二次繪制 時(shí)如果 為 false 則 不需要走 decode 方法,如果每次都是新引入的 json,那每次都走 decode 就會(huì)報(bào)錯(cuò)
      ————————————————

                              版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。
      

      原文鏈接:https://blog.csdn.net/m0_37805167/article/details/122553278

他建議是 Object.assign({}, json) 拷貝一次,解釋是異步獲取的數(shù)據(jù)是只讀的,echarts無(wú)法更改,所以會(huì)報(bào)錯(cuò),需要拷貝一下,確實(shí)在某些情況下能解決,但通過(guò)路由切換到需要畫圖的頁(yè)面上來(lái)時(shí),依然會(huì)報(bào)錯(cuò),目前還沒(méi)有找到靠譜的解決方案,可能不用json而是用js會(huì)解決這個(gè)問(wèn)題,需要我來(lái)確認(rèn)

http://m.risenshineclean.com/news/61457.html

相關(guān)文章:

  • 操作簡(jiǎn)單網(wǎng)站搭建費(fèi)用網(wǎng)站免費(fèi)搭建平臺(tái)
  • wordpress手機(jī)號(hào)網(wǎng)站企業(yè)seo培訓(xùn)
  • 中國(guó)的網(wǎng)站域名新媒體營(yíng)銷案例分析
  • 程序員做彩票網(wǎng)站違法嗎競(jìng)價(jià)廣告推廣
  • php+開發(fā)動(dòng)態(tài)網(wǎng)站開發(fā)百度推廣的四種收費(fèi)形式
  • 高端網(wǎng)站鑒賞哈爾濱百度搜索排名優(yōu)化
  • 網(wǎng)站開發(fā)外快百度自動(dòng)搜索關(guān)鍵詞軟件
  • 長(zhǎng)沙網(wǎng)紅美食seo型網(wǎng)站
  • 蔬菜基地做網(wǎng)站合適嗎金戈枸櫞酸西地那非片
  • 線上網(wǎng)站開發(fā)系統(tǒng)流程網(wǎng)絡(luò)營(yíng)銷的宏觀環(huán)境
  • 河南鄭州暴雨傷亡seo標(biāo)題優(yōu)化分析范文
  • 威海網(wǎng)站建設(shè)是什么seo基礎(chǔ)知識(shí)培訓(xùn)
  • 財(cái)務(wù)咨詢網(wǎng)站模板網(wǎng)站推廣的方式和方法
  • nas服務(wù)器 做網(wǎng)站推廣注冊(cè)app賺錢平臺(tái)
  • 網(wǎng)站續(xù)費(fèi)管理系統(tǒng)合肥網(wǎng)站排名提升
  • 網(wǎng)站開發(fā)學(xué)校推廣網(wǎng)站源碼
  • seo網(wǎng)站做推廣寧德市中醫(yī)院
  • 建英語(yǔ)網(wǎng)站好廣西網(wǎng)站建設(shè)
  • 網(wǎng)站建設(shè)的流程范文1500字百度指數(shù)網(wǎng)
  • 網(wǎng)站建設(shè)屬于什么行業(yè)分類網(wǎng)絡(luò)銷售怎么做才能做好
  • 網(wǎng)站建設(shè)高端培訓(xùn)目前引流最好的app
  • 專業(yè)國(guó)外建設(shè)網(wǎng)站遼寧和生活app下載安裝
  • 網(wǎng)站建設(shè) 徐州seo網(wǎng)絡(luò)推廣機(jī)構(gòu)
  • 織夢(mèng)cms零基礎(chǔ)做網(wǎng)站今日百度關(guān)鍵詞排名
  • c網(wǎng)站開發(fā)視頻教程萬(wàn)網(wǎng)注冊(cè)域名
  • 做網(wǎng)站的管理員咋找搜索引擎網(wǎng)站優(yōu)化和推廣方案
  • 訂餐網(wǎng)站開發(fā)方案北京seo公司
  • seo排行榜年度10佳網(wǎng)站最有效的線下推廣方式
  • 網(wǎng)站開發(fā)軟件測(cè)試報(bào)告寧德市高中階段招生信息平臺(tái)
  • 網(wǎng)站版權(quán)符號(hào)什么是搜索引擎營(yíng)銷