echarts【实战】饼状图点击高亮,其他区域变暗

最终效果

代码实现

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>饼图数值固定显示效果</title>
    <!-- 引入 ECharts -->
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js"></script>
    <style>
        body {
            padding: 20px;
        }
        #pieChart {
            width: 100%;
            height: 500px;
        }
    </style>
</head>
<body>
    <div id="pieChart"></div>

    <script>
        // 初始化图表
        const chartDom = document.getElementById('pieChart');
        const myChart = echarts.init(chartDom);
        let option;
        
        // 示例数据
        const pieData = [
            { value: 335, name: '直接访问' },
            { value: 310, name: '邮件营销' },
            { value: 234, name: '联盟广告' },
            { value: 135, name: '视频广告' },
            { value: 1548, name: '搜索引擎' }
        ];
        
        // 保存原始颜色和选中状态
        const originalColors = [];
        let selectedIndex = -1;
        const legendNames = pieData.map(item => item.name);
        
        // 颜色变暗函数
        function darkenColor(color, percent) {
            let hex = color.replace('#', '');
            let r = parseInt(hex.substring(0, 2), 16);
            let g = parseInt(hex.substring(2, 4), 16);
            let b = parseInt(hex.substring(4, 6), 16);
            
            r = Math.floor(r * (1 - percent/100));
            g = Math.floor(g * (1 - percent/100));
            b = Math.floor(b * (1 - percent/100));
            
            r = Math.max(0, Math.min(255, r));
            g = Math.max(0, Math.min(255, g));
            b = Math.max(0, Math.min(255, b));
            
            return '#' + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
        }
        
        // 初始化图表配置
        option = {
            tooltip: {
                trigger: 'item'
            },
            legend: {
                orient: 'vertical',
                left: 10,
                data: legendNames,
                textStyle: {
                    color: '#666',
                    fontSize: 14
                },
                emphasis: {
                    textStyle: {
                        color: '#e63946',
                        fontWeight: 'bold'
                    }
                }
            },
            series: [
                {
                    name: '访问来源',
                    type: 'pie',
                    radius: ['40%', '70%'],
                    center: ['60%', '50%'],
                    itemStyle: {
                        borderRadius: 10,
                        borderColor: '#fff',
                        borderWidth: 2
                    },
                    // 关键配置:固定显示标签和数值
                    label: {
                        show: true,  // 始终显示标签
                        position: 'outside',  // 标签显示在外侧
                        formatter: '{b}: {c} ({d}%)',  // 显示名称、数值和百分比
                        color: '#666',  // 普通状态标签颜色
                        fontSize: 12,
                        // 标签线配置
                        lineStyle: {
                            color: '#999',
                            width: 1
                        }
                    },
                    labelLine: {
                        show: true,  // 显示标签连接线
                        length: 15,
                        length2: 20
                    },
                    // 选中状态的配置
                    emphasis: {
                        scale: true,
                        scaleSize: 20,
                        itemStyle: {
                            shadowBlur: 10,
                            shadowColor: 'rgba(0, 0, 0, 0.3)'
                        },
                        // 选中时的标签高亮样式
                        label: {
                            color: '#e63946',  // 高亮颜色
                            fontSize: 14,
                            fontWeight: 'bold'
                        }
                    },
                    data: pieData
                }
            ],
            animationDuration: 300,
            animationEasing: 'elasticOut'
        };
        
        // 渲染图表并获取原始颜色
        myChart.setOption(option);
        const colorList = myChart.getOption().color || echarts.graphic.getDefaultColor();
        pieData.forEach((item, index) => {
            originalColors[index] = colorList[index % colorList.length];
        });
        
        // 处理点击事件
        myChart.on('click', function(params) {
            if (params.componentType === 'series' && params.seriesType === 'pie') {
                // 切换选中状态
                selectedIndex = selectedIndex === params.dataIndex ? -1 : params.dataIndex;
                updateChartStyle();
            } else if (params.componentType === 'legend') {
                // 处理图例点击
                const index = legendNames.indexOf(params.name);
                selectedIndex = selectedIndex === index ? -1 : index;
                updateChartStyle();
            } else {
                // 点击空白处取消选中
                selectedIndex = -1;
                updateChartStyle();
            }
        });
        
        // 更新图表样式
        function updateChartStyle() {
            option.series[0].data.forEach((item, index) => {
                if (index === selectedIndex) {
                    // 选中的扇区
                    item.itemStyle = {
                        color: originalColors[index]
                    };
                    myChart.dispatchAction({ type: 'highlight', seriesIndex: 0, dataIndex: index });
                    myChart.dispatchAction({ type: 'highlight', seriesIndex: 0, name: legendNames[index] });
                } else {
                    // 未选中的扇区
                    item.itemStyle = {
                        color: darkenColor(originalColors[index], 40)
                    };
                    myChart.dispatchAction({ type: 'downplay', seriesIndex: 0, dataIndex: index });
                    myChart.dispatchAction({ type: 'downplay', seriesIndex: 0, name: legendNames[index] });
                }
            });
            
            myChart.setOption(option);
        }
        
        // 响应窗口大小变化
        window.addEventListener('resize', () => {
            myChart.resize();
        });
    </script>
</body>
</html>
相关推荐
wow_DG18 小时前
【ECharts✨】解决Vue 中 v-show 导致组件 ECharts 样式异常问题
前端·javascript·vue.js·echarts
HashTang3 天前
2025年7月份实时最新获取地图边界数据方法,省市区县街道多级联动【文末附实时geoJson数据下载】
echarts·地图·geojson·全国geojson·经纬度·街道geojson·街道边界数据·矢量边界·乡镇geojson·乡镇边界数据·行政边界
全宝4 天前
🗾3分钟学会Echart地图下钻
前端·echarts
paopaokaka_luck7 天前
基于SpringBoot+Vue的汽车租赁系统(协同过滤算法、腾讯地图API、支付宝沙盒支付、WebsSocket实时聊天、ECharts图形化分析)
vue.js·spring boot·后端·websocket·算法·汽车·echarts
隐含7 天前
基于echarts的水球的样式。
前端·javascript·echarts
lianlian018 天前
vue3+echarts 多Y轴折线图,通过图例legend动态控制对应Y轴所有数据显示隐藏
echarts
托马斯-酷涛8 天前
基于Echarts的气象数据可视化网站系统的设计与实现(Python版)
python·信息可视化·echarts
鱼钓猫9 天前
echarts 堆叠柱状图 柱与柱之间设置上下水平间隙
前端·echarts
小彭努力中10 天前
153.在 Vue 3 中使用 OpenLayers + Cesium 实现 2D/3D 地图切换效果
前端·javascript·vue.js·3d·ecmascript·echarts