欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Vue3+ECharts實現(xiàn)動態(tài)地圖切換與平滑過渡的動畫效果

 更新時間:2025年08月06日 10:09:53   作者:CF14年老兵  
本文基于Vue3與ECharts5,實現(xiàn)市級地圖展示及區(qū)縣視圖切換,通過universalTransition和Canvas圖像處理技術(shù),打造平滑動畫與區(qū)域高亮效果,結(jié)合響應(yīng)式布局與交互優(yōu)化提升用戶體驗,需要的朋友可以參考下

本文將詳細(xì)解析如何使用 Vue3 和 ECharts 實現(xiàn)市級地圖展示功能,并添加地圖切換時的平滑過渡動畫效果。

  1. 使用 ECharts 的 universalTransition 實現(xiàn)地圖切換動畫
  2. 通過 Canvas 動態(tài)處理圖像實現(xiàn)區(qū)域高亮效果
  3. 設(shè)計響應(yīng)式布局確保地圖適應(yīng)不同屏幕尺寸
  4. 實現(xiàn)層級導(dǎo)航和交互反饋提升用戶體驗

功能概述

本組件實現(xiàn)了一個具有以下特性的地圖展示系統(tǒng):

  1. 展示河南省周口市行政區(qū)劃地圖
  2. 點擊地圖區(qū)域可切換到區(qū)縣級別視圖
  3. 地圖切換時帶有平滑的過渡動畫
  4. 自定義地圖樣式和交互效果
  5. 響應(yīng)式布局適應(yīng)不同屏幕尺寸

技術(shù)棧

  • Vue3(Composition API)
  • ECharts 5
  • TypeScript
  • Canvas 圖像處理

核心功能實現(xiàn)

1. 組件結(jié)構(gòu)與依賴

<template>
  <div id="mapChart" class="mt-4 w-full" ref="mapChartRef"></div>
</template>

<script setup lang="ts">
import * as echarts from 'echarts';
import mapBgImgSrc from '@/assets/images/map-bg.png';
import geoData from '@/assets/jeo/jeoMap.json';
import { ref, onMounted, nextTick } from 'vue';

// 組件引用和數(shù)據(jù)
const mapChartRef = ref<HTMLElement | null>(null);
const selectDistrictVal = ref('zhoukou'); // 當(dāng)前選中的地區(qū)
let myChart: echarts.ECharts | null = null; // ECharts實例

2. 動態(tài)創(chuàng)建遮罩背景圖

// 創(chuàng)建帶遮罩的背景圖像(用于高亮區(qū)域)
function createMaskedBgImg(src: string, maskColor = 'rgba(0,0,0,0.1)'): Promise<string> {
  return new Promise((resolve) => {
    const img = new Image();
    img.src = src;
    const canvas = document.createElement('canvas');
    
    img.onload = () => {
      canvas.width = img.width;
      canvas.height = img.height;
      const ctx = canvas.getContext('2d')!;
      
      // 繪制原始圖像
      ctx.drawImage(img, 0, 0);
      
      // 添加遮罩層
      ctx.fillStyle = maskColor;
      ctx.fillRect(0, 0, img.width, img.height);
      
      resolve(canvas.toDataURL());
    };
    
    img.onerror = () => resolve(src); // 失敗時返回原圖
  });
}

3. 地圖配置生成器

// 生成ECharts地圖配置
const getMapOption = (mapType = 'zhoukou', maskedBgImg = mapBgImgSrc) => {
  // 從GeoJSON數(shù)據(jù)中提取當(dāng)前區(qū)域
  const feature = geoData.features.find(
    (f: any) => f.properties.name === mapType
  );
  
  const mapGeoData = mapType === 'zhoukou' 
    ? geoData 
    : { 
        type: 'FeatureCollection', 
        features: feature ? [feature] : [] 
      };
  
  // 注冊地圖數(shù)據(jù)
  echarts.registerMap('zhoukou', mapGeoData as any);
  
  return {
    // 動畫配置
    animation: true,
    animationDuration: 800,
    animationEasing: 'cubicOut' as any,
    animationDurationUpdate: 800,
    animationEasingUpdate: 'cubicOut' as any,
    
    // 標(biāo)題
    title: {
      top: 10,
      text: mapType === 'zhoukou' ? '河南省 - 周口市' : `周口市 - ${mapType}`,
      x: 'center',
      textStyle: {
        color: '#2564AD',
        fontWeight: 600,
        fontSize: 16
      }
    },
    
    // 地理坐標(biāo)系配置
    geo: {
      map: 'zhoukou',
      aspectScale: 0.8,
      layoutCenter: ['50.6%', '51%'],
      layoutSize: '91.5%',
      roam: false,
      z: 0,
      itemStyle: {
        areaColor: '#2564AD',
        borderColor: '#2564AD',
        borderWidth: 1
      }
    },
    
    // 地圖系列
    series: [{
      type: 'map',
      map: 'zhoukou',
      universalTransition: { 
        enabled: true, 
        divideShape: 'clone'  // 關(guān)鍵:啟用形狀分割動畫
      },
      zoom: 1.2,
      itemStyle: {
        areaColor: { image: mapBgImgSrc, repeat: 'repeat' },
        borderColor: '#80AACC',
        borderWidth: 2
      },
      emphasis: { // 鼠標(biāo)懸停樣式
        itemStyle: {
          areaColor: { image: maskedBgImg, repeat: 'repeat' },
          borderColor: '#80AACC'
        },
        label: { color: '#409eff', fontWeight: 'bold' }
      },
      select: { // 選中區(qū)域樣式
        itemStyle: {
          areaColor: { image: maskedBgImg, repeat: 'repeat' },
          borderColor: '#80AACC'
        },
        label: { color: '#409eff', fontWeight: 'bold' }
      },
      label: { // 區(qū)域標(biāo)簽
        show: true,
        color: '#80AACC',
        fontWeight: 'bold'
      }
    }]
  };
};

4. 地圖初始化與交互

// 初始化地圖
const initMap = async () => {
  if (!mapChartRef.value) return;
  
  // 創(chuàng)建ECharts實例
  myChart = echarts.init(mapChartRef.value);
  
  // 創(chuàng)建遮罩背景圖
  const maskedBgImg = await createMaskedBgImg(
    mapBgImgSrc, 
    'rgba(0,0,0,0.1)'
  );
  
  // 設(shè)置初始配置
  myChart.setOption(getMapOption('zhoukou', maskedBgImg), false);
  
  // 添加點擊事件處理
  myChart.on('click', function (e: any) {
    if (!e.name || typeof e.name !== 'string') return;
    
    // 只有在地級市視圖時才能點擊進入?yún)^(qū)縣
    if (selectDistrictVal.value === 'zhoukou') {
      myChart.setOption(getMapOption(e.name, maskedBgImg), false);
      selectDistrictVal.value = e.name;
    }
  });
};

// 響應(yīng)式調(diào)整地圖尺寸
const setMapView = async () => {
  await nextTick();
  if (mapChartRef.value?.parentNode) {
    const parentHeight = mapChartRef.value.parentNode.offsetHeight;
    const siblingHeight = mapChartRef.value.previousSibling?.offsetHeight || 0;
    mapChartRef.value.style.height = `${parentHeight - siblingHeight - 16}px`;
  }
  
  // 窗口大小變化時重繪
  window.addEventListener('resize', () => {
    myChart?.resize();
  });
};

// 組件掛載時初始化
onMounted(async () => {
  await setMapView();
  initMap();
});

// 暴露外部控制方法
defineExpose({
  getCurrentDistrict: () => selectDistrictVal.value,
  
  setDistrict: async (district: string) => {
    selectDistrictVal.value = district;
    const maskedBgImg = await createMaskedBgImg(
      mapBgImgSrc, 
      'rgba(0,0,0,0.1)'
    );
    myChart?.setOption(getMapOption(district, maskedBgImg), false);
  }
});
</script>

關(guān)鍵技術(shù)與優(yōu)化點

1. 平滑過渡動畫實現(xiàn)

通過以下配置實現(xiàn)地圖切換時的平滑動畫效果:

// 關(guān)鍵動畫配置
universalTransition: { 
  enabled: true, 
  divideShape: 'clone'  // 形狀分割動畫
},
animationDuration: 800,
animationEasing: 'cubicOut',
animationDurationUpdate: 800,
animationEasingUpdate: 'cubicOut'

universalTransition 是 ECharts 5 引入的強大功能,它允許在數(shù)據(jù)更新時自動生成過渡動畫,特別適合地理區(qū)域的切換。

2. Canvas 動態(tài)圖像處理

使用 Canvas 動態(tài)生成帶遮罩的背景圖,實現(xiàn)區(qū)域高亮效果:

// 創(chuàng)建帶遮罩的背景圖
ctx.drawImage(img, 0, 0); // 繪制原圖
ctx.fillStyle = maskColor; // 設(shè)置遮罩顏色
ctx.fillRect(0, 0, img.width, img.height); // 繪制遮罩層

3. 響應(yīng)式布局處理

// 動態(tài)計算地圖容器高度
const parentHeight = mapChartRef.value.parentNode.offsetHeight;
const siblingHeight = mapChartRef.value.previousSibling?.offsetHeight || 0;
mapChartRef.value.style.height = `${parentHeight - siblingHeight - 16}px`;

// 監(jiān)聽窗口大小變化
window.addEventListener('resize', () => {
  myChart?.resize();
});

4. 交互體驗優(yōu)化

  • 層級導(dǎo)航:只能從市級視圖進入?yún)^(qū)縣視圖,防止無限深入
  • 視覺反饋:懸停和選中狀態(tài)有明顯樣式變化
  • 標(biāo)題動態(tài)更新:根據(jù)當(dāng)前視圖級別顯示不同標(biāo)題
  • 性能優(yōu)化:使用 false 參數(shù)避免不必要的重繪
myChart.setOption(getMapOption(e.name, maskedBgImg), false);

使用示例

在父組件中使用地圖組件

<template>
  <div class="container">
    <h1>河南省行政區(qū)劃地圖</h1>
    <div class="controls">
      <button @click="backToCity">返回市級視圖</button>
      <select v-model="selectedDistrict" @change="changeDistrict">
        <option value="zhoukou">周口市</option>
        <option value="taikang">太康縣</option>
        <option value="huaiyang">淮陽縣</option>
        <!-- 其他區(qū)縣選項 -->
      </select>
    </div>
    <MapComponent ref="mapRef" />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import MapComponent from './MapComponent.vue';

const mapRef = ref();
const selectedDistrict = ref('zhoukou');

// 切換區(qū)縣
const changeDistrict = () => {
  mapRef.value.setDistrict(selectedDistrict.value);
};

// 返回市級視圖
const backToCity = () => {
  selectedDistrict.value = 'zhoukou';
  mapRef.value.setDistrict('zhoukou');
};
</script>

總結(jié)

以上就是基于Vue3+ECharts實現(xiàn)動態(tài)地圖切換與平滑過渡的動畫效果的詳細(xì)內(nèi)容,更多關(guān)于Vue3 ECharts地圖切換與平滑過渡的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 使用ElementUI寫一個前端分頁查詢的實例

    使用ElementUI寫一個前端分頁查詢的實例

    本文主要介紹了使用ElementUI寫一個前端分頁查詢的實例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 對Vue table 動態(tài)表格td可編輯的方法詳解

    對Vue table 動態(tài)表格td可編輯的方法詳解

    今天小編就為大家分享一篇對Vue table 動態(tài)表格td可編輯的方法詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • vue3使用useDialog實現(xiàn)對話框的示例代碼

    vue3使用useDialog實現(xiàn)對話框的示例代碼

    在日常開發(fā)中,彈窗是常見的一個功能,本文主要介紹了vue3使用useDialog實現(xiàn)對話框的示例代碼,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • Vue創(chuàng)建頭部組件示例代碼詳解

    Vue創(chuàng)建頭部組件示例代碼詳解

    本文通過實例代碼給大家介紹了Vue創(chuàng)建頭部組件的相關(guān)知識,非常不錯,具有一定的參考借鑒價值 ,需要的朋友可以參考下
    2018-10-10
  • vue3+vite+tdesign實現(xiàn)日歷式可編輯的排課班表填寫功能

    vue3+vite+tdesign實現(xiàn)日歷式可編輯的排課班表填寫功能

    本文介紹了如何使用Vue3和tdesign實現(xiàn)一個日歷式、可編輯的排班填寫功能,開發(fā)過程中面臨了年份和月份下拉框的實現(xiàn)、周期顯示以及可編輯日歷的樣式和數(shù)據(jù)獲取等挑戰(zhàn),感興趣的朋友一起看看吧
    2025-01-01
  • vite+vue3中require?is?not?defined問題及解決

    vite+vue3中require?is?not?defined問題及解決

    這篇文章主要介紹了vite+vue3中require?is?not?defined問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Vue之生命周期函數(shù)詳解

    Vue之生命周期函數(shù)詳解

    這篇文章主要為大家介紹了Vue之生命周期函數(shù),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2021-11-11
  • Vue.js雙向綁定操作技巧(初級入門)

    Vue.js雙向綁定操作技巧(初級入門)

    這篇文章主要介紹了Vue.js雙向綁定操作技巧(初級入門)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-12-12
  • 基于Vue2實現(xiàn)歌曲播放和歌詞滾動效果

    基于Vue2實現(xiàn)歌曲播放和歌詞滾動效果

    這篇文章主要介紹了如何基于Vue2實現(xiàn)歌曲播放和歌詞滾動效果,文中通過代碼示例和圖文講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以自己動手試一下
    2024-09-09
  • vue連接本地服務(wù)器的實現(xiàn)示例

    vue連接本地服務(wù)器的實現(xiàn)示例

    本文主要介紹了vue連接本地服務(wù)器的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01

最新評論