最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于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)化提升用戶體驗,需要的朋友可以參考下

本文將詳細解析如何使用 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)地圖切換與平滑過渡的動畫效果的詳細內(nèi)容,更多關(guān)于Vue3 ECharts地圖切換與平滑過渡的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue中axios封裝使用的完整教程

    vue中axios封裝使用的完整教程

    這篇文章主要給大家介紹了關(guān)于vue中axios封裝使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • vue登錄成功之后的token處理詳細步驟

    vue登錄成功之后的token處理詳細步驟

    Token是身份驗證后服務(wù)端返回的令牌,常用于訪問授權(quán)API和頁面權(quán)限校驗,Token數(shù)據(jù)可存儲在本地或Vuex中,本地存儲可實現(xiàn)數(shù)據(jù)持久化,這篇文章主要介紹了vue登錄成功之后的token處理詳細步驟,需要的朋友可以參考下
    2024-10-10
  • Vue2中實現(xiàn)輸入中文自動轉(zhuǎn)化為拼音且不帶音調(diào)的實現(xiàn)方案

    Vue2中實現(xiàn)輸入中文自動轉(zhuǎn)化為拼音且不帶音調(diào)的實現(xiàn)方案

    文章介紹了在Vue2中實現(xiàn)輸入中文自動轉(zhuǎn)化為拼音且不帶音調(diào)的幾種方案,包括使用pinyin庫、自定義指令、計算屬性、帶防抖的優(yōu)化版本以及使用其他拼音庫,推薦使用方案一和方案三,因其實現(xiàn)簡單且易于維護,感興趣的朋友跟隨小編一起看看吧
    2025-12-12
  • Vue中的組件詳談

    Vue中的組件詳談

    這篇文章主要介紹了Vue的組件,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-10-10
  • 關(guān)于vue-router的使用及實現(xiàn)原理

    關(guān)于vue-router的使用及實現(xiàn)原理

    這篇文章主要介紹了關(guān)于vue-router的使用及實現(xiàn)原理,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • vue實現(xiàn)數(shù)字滾動效果

    vue實現(xiàn)數(shù)字滾動效果

    這篇文章主要為大家詳細介紹了vue實現(xiàn)數(shù)字滾動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Vue學(xué)習(xí)筆記進階篇之過渡狀態(tài)詳解

    Vue學(xué)習(xí)筆記進階篇之過渡狀態(tài)詳解

    本篇文章主要介紹了Vue學(xué)習(xí)筆記進階篇之過渡狀態(tài)詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • vue實現(xiàn)簡易的計算器功能

    vue實現(xiàn)簡易的計算器功能

    這篇文章主要為大家詳細介紹了vue實現(xiàn)簡易的計算器功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-11-11
  • 詳解如何運行vue項目

    詳解如何運行vue項目

    這篇文章主要介紹了如何運行vue項目,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • vue中使用scrollTo沒有效果的完美解決方法

    vue中使用scrollTo沒有效果的完美解決方法

    這篇文章主要介紹了在vue中使用scrollTo沒有效果的解決方法,本文給大家分享具體操作步驟,在這里需要注意scrollTo要作用在可滾動的元素上,不然不生效,scrollTop就會一直為0,需要的朋友可以參考下
    2023-10-10

最新評論

新民市| 钟山县| 建德市| 沁阳市| 扎囊县| 文化| 天镇县| 启东市| 视频| 阿瓦提县| 合作市| 宁强县| 八宿县| 昌宁县| 景德镇市| 成武县| 遂溪县| 永年县| 铜梁县| 宁安市| 墨江| 顺昌县| 徐水县| 新龙县| 波密县| 准格尔旗| 孝昌县| 华坪县| 亳州市| 罗山县| 武冈市| 廉江市| 嘉祥县| 五家渠市| 仁布县| 永济市| 社会| 玉龙| 普定县| 禹州市| 泊头市|