vue3.2 + echarts5.6 + ant-design-vue 3.x 實現自定義 echarts 圖例

文章目錄

    • 概要
    • 技術細節
    • 效果

概要

需求需要實現圖例移入顯示描述說明
故實現自定義圖例

技術細節

<template><div class="custom-legend"><divv-for="item in legends":key="item.name"class="legend-item":class="{ 'is-disabled': !isItemActive(item.name) }"@click="toggleLegend(item)"><spanclass="legend-marker":style="{ backgroundColor: item.color }"></span><a-tooltip><template #title><span>{{ item.tooltip || item.name }}</span></template><span>{{ item.name }}</span></a-tooltip></div></div>
</template><script setup>
import { ref, computed, watch, onMounted, onBeforeUnmount } from 'vue'const props = defineProps({chartInstance: {type: Object,default: () => null},customTooltips: {type: Object,default: () => ({})}
})const legends = ref([])
const activeMap = ref({})const isItemActive = computed(() => (name) => {return activeMap.value[name]
})const toggleLegend = (item) => {if (!props.chartInstance) returnconst name = item.nameconst newState = !activeMap.value[name]activeMap.value = { ...activeMap.value, [name]: newState }props.chartInstance.setOption({legend: {selected: activeMap.value}})
}const renderLegends = () => {if (!props.chartInstance) {legends.value = []return}const chart = props.chartInstanceconst options = chart.getOption()const { series, color: globalColors, legend } = optionsconst chartSelectedMap = legend?.[0]?.selected || {}activeMap.value = { ...chartSelectedMap }const legendItems = []series.forEach((seriesItem, seriesIndex) => {if (seriesItem.type === 'pie') {seriesItem.data.forEach((dataItem, dataIndex) => {const name = dataItem.nameconst color =dataItem.itemStyle?.color ||globalColors[dataIndex % globalColors.length] ||'#000'if (activeMap.value[name] === undefined) {activeMap.value[name] = true}legendItems.push({name,color,tooltip: props.customTooltips[name] || name})})} else {const name = seriesItem.nameconst color =seriesItem.itemStyle?.color ||globalColors[seriesIndex % globalColors.length] ||'#000'if (activeMap.value[name] === undefined) {activeMap.value[name] = true}legendItems.push({name,color,tooltip: props.customTooltips[name] || name})}})legends.value = legendItems
}const handleChartLegendChange = (params) => {activeMap.value = { ...params.selected }
}watch(() => props.chartInstance,(newVal) => {if (newVal) {renderLegends()} else {legends.value = []}},{ immediate: true }
)
</script><style scoped lang="scss">
.custom-legend {display: flex;flex-wrap: wrap;justify-content: center;gap: 12px;padding: 8px;.legend-item {display: flex;align-items: center;gap: 6px;cursor: pointer;transition: all 0.2s ease;.legend-marker {width: 14px;height: 14px;border-radius: 50%;transition: all 0.2s ease;}&.is-disabled {opacity: 0.6;.legend-marker {filter: grayscale(100%);transform: scale(0.9);}}&:hover:not(.is-disabled) {transform: translateY(-1px);opacity: 0.9;}}
}
</style>
<template><div class="container"><div class="chart" ref="lineChart"></div><div class="chart" ref="pieChart"></div><div class="legend1"><Legend :chartInstance="chartInstance1" /></div><div class="legend2"><Legend :chartInstance="chartInstance2" /></div></div>
</template>
<script setup>
import * as echarts from 'echarts'
import Legend from './components/Legend.vue'const lineChart = ref(null)
const pieChart = ref(null)const chartInstance1 = shallowRef(null)
const chartInstance2 = shallowRef(null)const _data = {line: {title: '折線圖示例',categories: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],legend: ['郵件營銷', '聯盟廣告', '視頻廣告', '直接訪問', '搜索引擎'],series: [{name: '郵件營銷',type: 'line',data: [120, 132, 101, 134, 90, 230, 210]},{name: '聯盟廣告',type: 'line',data: [220, 182, 191, 234, 290, 330, 310]},{name: '視頻廣告',type: 'line',data: [150, 232, 201, 154, 190, 330, 410]},{name: '直接訪問',type: 'line',data: [320, 332, 301, 334, 390, 330, 320]},{name: '搜索引擎',type: 'line',data: [820, 932, 901, 934, 1290, 1330, 1320]}]},pie: {title: '餅圖示例',legend: ['直接訪問', '郵件營銷', '聯盟廣告', '視頻廣告', '搜索引擎'],series: [{ value: 335, type: 'pie', name: '直接訪問' },{ value: 310, type: 'pie', name: '郵件營銷' },{ value: 234, type: 'pie', name: '聯盟廣告' },{ value: 135, type: 'pie', name: '視頻廣告' },{ value: 1548, type: 'pie', name: '搜索引擎' }]}
}const onItemClick = (params) => {chartInstance1.value.dispatchAction({type: 'legendToggleSelect',name: params.name})
}const initChart = () => {const lineOption = {title: {text: _data.line.title},tooltip: {trigger: 'axis'},legend: {show: false},grid: {left: '3%',right: '4%',bottom: '3%',containLabel: true},xAxis: {type: 'category',boundaryGap: false,data: _data.line.categories},yAxis: {type: 'value'},series: _data.line.series}const pieOption = {title: {text: _data.pie.title},tooltip: {trigger: 'item',formatter: '{a} <br/>{b} : {c} ({d}%)'},legend: {show: false},series: [{name: '訪問來源',type: 'pie',radius: '55%',center: ['50%', '60%'],data: _data.pie.series,itemStyle: {emphasis: {shadowBlur: 10,shadowOffsetX: 0,shadowColor: 'rgba(0, 0, 0, 0.5)'}}}]}const lineChartDom = lineChart.valueconst pieChartDom = pieChart.valueconst lineChartInstance = echarts.init(lineChartDom)const pieChartInstance = echarts.init(pieChartDom)lineChartInstance.setOption(lineOption)pieChartInstance.setOption(pieOption)chartInstance1.value = lineChartInstancechartInstance2.value = pieChartInstance
}onMounted(() => {initChart()
})
</script><style lang="scss" scoped>
.container {display: flex;width: 1200px;justify-content: space-between;margin-top: 20px;position: relative;.chart {width: 49%;height: 400px;}.legend1 {position: absolute;bottom: -50px;left: 50px;}.legend2 {position: absolute;bottom: -50px;right: 50px;}
}
</style>

效果

在這里插入圖片描述
在這里插入圖片描述
在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916556.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916556.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916556.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【2025年7月25日】TrollStore巨魔商店恢復在線安裝

就在今日7月25日&#xff0c;TrollStore的在線安裝功能再次變得可用&#xff0c;這對于許多iPhone用戶來說無疑是個喜訊。在經歷了近三個月的中斷后&#xff0c;巨魔商店的企業證書意外的到來了&#xff0c;使得用戶能夠重新采用在線安裝的方式&#xff01; 在線安裝地址在文…

【05】C#入門到精通——C# 面向對象、類、靜態變量static、類與類之間的調用

文章目錄1 引入例子2 創建類2.1 類的訪問屬性2.2 英雄 特點類2.3 英雄信息打印3 靜態變量static4 類 調用 類4.1 非靜態 成員函數4.2 靜態 成員函數1 引入例子 比如游戲中 描述英雄的角色&#xff0c; 我們可以像下面這樣&#xff0c;給每一個英雄特點及擁有技能分別定義變量…

單片機的硬件結構

單片機的硬件結構 一、課程導入 在上一節課《認識單片機》中&#xff0c;我們知道單片機就像一個超級迷你的工廠&#xff0c;有著類似工廠的各個組成部分。而這個 “迷你工廠” 能正常運轉&#xff0c;離不開其內部嚴謹的硬件結構。就像一座大廈&#xff0c;只有基礎結構穩固且…

multiprocessing模塊使用方法(二)

spawn_main是Python multiprocessing模塊的核心內部函數&#xff0c;用于實現spawn啟動方法的子進程初始化。以下結合代碼Demo詳細說明其使用方法和推薦場景。一、spawn_main的功能與定位核心作用&#xff1a; 在spawn模式下啟動子進程&#xff0c;負責進程間通信管道的建立和資…

編程與數學 03-002 計算機網絡 07_路由算法

編程與數學 03-002 計算機網絡 07_路由算法一、靜態路由算法&#xff08;一&#xff09;手工配置路由表的方法&#xff08;二&#xff09;靜態路由的優缺點二、動態路由算法原理&#xff08;一&#xff09;距離矢量算法&#xff08;如貝爾曼 - 福特算法&#xff09;&#xff08…

使用Python,OpenCV計算跑圖的圖像彩色度

使用Python&#xff0c;OpenCV計算跑圖的圖像彩色度 這篇博客將介紹如何計算跑圖里最鮮艷的top25圖片和最灰暗的top25圖片并顯示色彩彩色度值展示。 效果圖 以下分別是最鮮艷top25和最灰暗top25對比效果圖&#xff1a; 最鮮艷top25效果圖&#xff1a; 最灰暗top25效果圖…

LeetCode 60:排列序列

LeetCode 60&#xff1a;排列序列問題定義與核心挑戰 給定整數 n 和 k&#xff0c;返回集合 {1,2,...,n} 的第 k 個字典序排列。直接生成所有排列再遍歷到第 k 個的方法&#xff08;時間復雜度 O(n!)&#xff09;會因 n≥10 時階乘爆炸而超時&#xff0c;因此需要 數學推導 貪…

亞遠景-傳統功能安全VS AI安全:ISO 8800填補的標準空白與實施難點

一、為什么需要ISO 8800&#xff1a;傳統安全標準的“盲區”傳統功能安全&#xff08;ISO 26262&#xff09;? 假設&#xff1a;系統行為可被完整規格化&#xff0c;失效模式可枚舉&#xff0c;風險可用概率-危害矩陣量化。? 盲區&#xff1a;對“設計意圖正確&#xff0c;但…

菜鳥教程 R語言基礎運算 注釋 和數據類型

菜鳥教程 R語言基礎運算 注釋 和數據類型 1.注釋 注釋主要用于一段代碼的解析&#xff0c;可以讓閱讀者更易理解&#xff0c;編程語言的注釋會被編譯器忽略掉&#xff0c;且不會影響代碼的執行。 一般編程語言的注釋分為單行注釋與多行注釋&#xff0c;但是 R 語言只支持單行注…

華為云ELB(彈性負載均衡)持續報異常

華為云ELB&#xff08;彈性負載均衡&#xff09;持續報異常&#xff0c;需結合實例類型&#xff08;共享型/獨享型&#xff09;和異常代碼進行針對性排查。以下是分步排查建議&#xff1a;一、根據實例類型排查網絡配置共享型實例 安全組規則&#xff1a;檢查后端服務器安全組是…

《R for Data Science (2e)》免費中文翻譯 (第2章) --- Workflow: basics

寫在前面 本系列推文為《R for Data Science (2)》的中文翻譯版本。所有內容都通過開源免費的方式上傳至Github&#xff0c;歡迎大家參與貢獻&#xff0c;詳細信息見&#xff1a; Books-zh-cn 項目介紹&#xff1a; Books-zh-cn&#xff1a;開源免費的中文書籍社區 r4ds-zh-cn …

開源深度學習新寵:Burn框架助您無憂高效建模

在日新月異的人工智能世界里&#xff0c;各類深度學習框架如雨后春筍般涌現&#xff0c;而Burn&#xff0c;作為新一代的深度學習框架&#xff0c;以其不妥協的靈活性、高效性和可移植性嶄露頭角。本文將深入探討Burn的核心功能、應用場景及具體使用方法&#xff0c;幫助您更好…

基于深度學習的圖像分割:使用DeepLabv3實現高效分割

前言 圖像分割是計算機視覺領域中的一個重要任務&#xff0c;其目標是將圖像中的每個像素分配到不同的類別中。近年來&#xff0c;深度學習技術&#xff0c;尤其是卷積神經網絡&#xff08;CNN&#xff09;&#xff0c;在圖像分割任務中取得了顯著的進展。DeepLabv3是一種高效的…

如何高效合并音視頻文件(時間短消耗資源少)(二)

英語字幕 1 00:00:06,480 --> 00:00:08,400 Good morning. We have a banger for you2 00:00:08,400 --> 00:00:09,840 today. We&amp;#39;re going to launch chatbt3 00:00:09,840 --> 00:00:11,519 agent. But before jumping into that, I&amp;#39;d4 00…

內網后滲透攻擊過程(實驗環境)--4、權限維持(2)

用途限制聲明&#xff0c;本文僅用于網絡安全技術研究、教育與知識分享。文中涉及的滲透測試方法與工具&#xff0c;嚴禁用于未經授權的網絡攻擊、數據竊取或任何違法活動。任何因不當使用本文內容導致的法律后果&#xff0c;作者及發布平臺不承擔任何責任。滲透測試涉及復雜技…

CentOS 9 配置國內 YUM 源

1.備份 sudo mv /etc/yum.repos.d/centos.repo /etc/yum.repos.d/centos.repo.backup sudo mv /etc/yum.repos.d/centos-addons.repo /etc/yum.repos.d/centos-addons.repo.backup2.創建新文件 vi /etc/yum.repos.d/centos.repo[baseos] nameCentOS Stream $releasever - BaseO…

【算法】遞歸、搜索與回溯算法入門

文章目錄遞歸什么是遞歸為什么會用到遞歸如何理解遞歸如何寫好一個遞歸搜索 vs 深度優先遍歷 vs 深度優先搜索 vs 寬度&#xff08;廣度&#xff09;優先遍歷 vs 寬度&#xff08;廣度&#xff09;優先搜索 vs 暴搜深度優先遍歷 vs 深度優先搜索&#xff08;dfs&#xff09;寬度…

借助Aspose.HTML控件,在 Python 中將 SVG 轉換為 PDF

您可能會發現許多解決方案都提供以編程方式將SVG轉換為PDF 的功能。但這篇博文將介紹一個功能強大的 SDK&#xff0c;供 Python 開發人員自動化文件轉換和操作。本指南將重點介紹通過 .NET 實現 Python 的 Aspose.HTML。此外&#xff0c;我們將逐步講解相關步驟和代碼片段&…

高級06-Java網絡編程:從Socket到HTTP

引言&#xff1a;Java 網絡編程的重要性 隨著互聯網技術的飛速發展&#xff0c;網絡編程已成為現代軟件開發中不可或缺的一部分。Java 作為一種廣泛應用于企業級開發和分布式系統的編程語言&#xff0c;提供了強大的網絡通信支持。從底層的 Socket 編程到高層的 HTTP 協議處理&…

STM32的藍牙通訊(HAL庫)

藍牙基礎知識&#xff08;了解即可&#xff09;&#xff1a;1.是一種利用低功率無線電&#xff0c;支持設備短距離通信的無線電技術&#xff0c;能在包括移動電話、PDAQ、無線耳機、筆記本電腦、相關外設等眾多設備之間進行無線信息交換&#xff0c;藍牙工作在全球通用的2.4 GH…