ECharts里面 tooltip中要显示百分号% 和tooltip对齐问题

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

需求:有一个统计报表,显示一个人一周的时间分布,看他的学习占比,和工作占比。鼠标移动到tooltip内容的时候,发现百分比没有显示%。需要让他显示

在这里插入图片描述

代码示例:

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>周时间分布统计</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js"></script>
    <style>
        body {
            font-family: 'Menlo', 'Consolas', monospace;
        }
    </style>
</head>

<body>
    <div id="main" style="width: 1200px;height:600px;"></div>
    <script>
        const chart = echarts.init(document.getElementById('main'))

        // 数据配置
        const dataConfig = {
            days: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
            categories: ['工作', '休息', '娱乐', '学习', '社交'],
            timeData: [
                [8, 2, 3, 2, 1],
                [9, 1, 2, 2, 2],
                [7, 3, 2, 3, 1],
                [8, 2, 2, 2, 2],
                [7, 1, 3, 3, 2],
                [4, 4, 6, 2, 4],
                [3, 5, 5, 3, 4]
            ],
            getPercentData: (typeIndex) => {
                return dataConfig.timeData.map(day => {
                    const total = day.reduce((a, b) => a + b, 0)
                    return Number(((day[typeIndex] / total) * 100).toFixed(2))
                })
            }
        }

        const option = {
            tooltip: {
                trigger: 'axis',
                axisPointer: {
                    type: 'shadow'
                },
            },
            legend: {
                data: [...dataConfig.categories, '学习占比', '工作占比'],
                textStyle: {
                    fontSize: 14
                }
            },
            xAxis: [{
                type: 'category',
                data: dataConfig.days,
                axisLabel: {
                    fontSize: 14
                }
            }],
            yAxis: [{
                type: 'value',
                name: '时间(小时)',
                min: 0,
                max: 24,
                axisLabel: {
                    fontSize: 14
                }
            }, {
                type: 'value',
                name: '占比',
                min: 0,
                max: 100,
                // 移除了Y轴标签的%符号
                axisLabel: {
                    formatter: '{value}',
                    fontSize: 14
                }
            }],
            series: [
                ...dataConfig.categories.map((name, idx) => ({
                    name,
                    type: 'bar',
                    stack: 'time',
                    data: dataConfig.timeData.map(day => day[idx]),
                    itemStyle: {
                        color: ['#5470C6', '#91CC75', '#FAC858', '#EE6666', '#73C0DE'][idx]
                    }
                })), {
                    name: '学习占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(3),
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: {
                        color: '#EE6666'
                    }
                }, {
                    name: '工作占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(0),
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: {
                        color: '#5470C6'
                    }
                }
            ]
        }

        chart.setOption(option);
    </script>
</body>

</html>

(1)自定义tooltip格式化函数

具体步骤可能包括:

  1. 在tooltip配置中添加formatter函数。
  2. 在formatter函数中遍历所有当前触发的数据点。
  3. 对每个数据点,判断其系列名称,如果是百分比系列,则在数值后添加%。
  4. 确保数值格式化正确,例如保留两位小数

在这里插入图片描述

代码示例:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>周时间分布统计</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js"></script>
    <style>
        body { font-family: 'Menlo', 'Consolas', monospace; }
    </style>
</head>
<body>
    <div id="main" style="width: 1200px;height:600px;"></div>
    <script>
        const chart = echarts.init(document.getElementById('main'));

        // 数据配置
        const dataConfig = {
            days: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
            categories: ['工作', '休息', '娱乐', '学习', '社交'],
            timeData: [
                [8, 2, 3, 2, 1],  
                [9, 1, 2, 2, 2],  
                [7, 3, 2, 3, 1],  
                [8, 2, 2, 2, 2],  
                [7, 1, 3, 3, 2],  
                [4, 4, 6, 2, 4],  
                [3, 5, 5, 3, 4]   
            ],
            getPercentData: (typeIndex) => {
                return dataConfig.timeData.map(day => {
                    const total = day.reduce((a,b) => a + b, 0);
                    return Number(((day[typeIndex]/total)*100).toFixed(2));
                })
            }
        };

        const option = {
            tooltip: {
                trigger: 'axis',
                axisPointer: { type: 'shadow' },
                formatter: (params) => {
                    const day = params[0].axisValue;
                    let result = `<b>${day}</b><br>`;
                    
                    // 修复点:直接使用p.value
                    const timeItems = params
                        .filter(p => p.seriesType === 'bar')
                        .map(p => `${p.marker} ${p.seriesName}: ${p.value}小时`); // 直接取value
                    
                    const percentItems = params
                        .filter(p => p.seriesType === 'line')
                        .map(p => `${p.marker} ${p.seriesName}: ${p.value}%`);

                    return [...timeItems, ...percentItems].join('<br>');
                }
            },
            legend: {
                data: [...dataConfig.categories, '学习占比', '工作占比'],
                textStyle: { fontSize: 14 }
            },
            xAxis: [{
                type: 'category',
                data: dataConfig.days,
                axisLabel: { fontSize: 14 }
            }],
            yAxis: [
                { 
                    type: 'value',
                    name: '时间(小时)',
                    min: 0,
                    max: 24,
                    axisLabel: { fontSize: 14 }
                },
                { 
                    type: 'value',
                    name: '占比',
                    min: 0,
                    max: 100,
                    axisLabel: { 
                        formatter: '{value}%',
                        fontSize: 14
                    }
                }
            ],
            series: [
                // 堆叠柱状图系列
                ...dataConfig.categories.map((name, idx) => ({
                    name,
                    type: 'bar',
                    stack: 'time',
                    data: dataConfig.timeData.map(day => day[idx]), // 数据格式为单值数组
                    itemStyle: {
                        color: ['#5470C6','#91CC75','#FAC858','#EE6666','#73C0DE'][idx]
                    }
                })),
                // 折线图系列
                {
                    name: '学习占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(3),
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: { color: '#EE6666' }
                },
                {
                    name: '工作占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(0),
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: { color: '#5470C6' }
                }
            ]
        };

        chart.setOption(option);
    </script>
</body>
</html>

或者,这样并没有两端对齐,可以加一些代码实现Tooltip两端对齐

  • 使用display: table创建表格布局,设置table-layout: fixed固定列宽
  • 定义两列:名称列(name-col)120px,数值列(value-col)100px
  • 数值列设置text-align: right实现右对齐

在这里插入图片描述

示例:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>周时间分布统计</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js"></script>
    <style>
        body { 
            font-family: 'Menlo', 'Consolas', monospace; 
        }
        /* Tooltip表格布局样式 */
        .tooltip-table {
            display: table;
            table-layout: fixed;
            width: 240px;
        }
        .tooltip-row {
            display: table-row;
        }
        .tooltip-cell {
            display: table-cell;
            padding: 2px 0;
            vertical-align: middle;
        }
        .name-col {
            width: 120px;
            padding-right: 10px;
        }
        .value-col {
            width: 100px;
            text-align: right;
        }
    </style>
</head>
<body>
    <div id="main" style="width: 1200px;height:600px;"></div>
    <script>
        const chart = echarts.init(document.getElementById('main'));

        // 数据配置
        const dataConfig = {
            days: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
            categories: ['工作', '休息', '娱乐', '学习', '社交'],
            timeData: [
                [8, 2, 3, 2, 1],  
                [9, 1, 2, 2, 2],  
                [7, 3, 2, 3, 1],  
                [8, 2, 2, 2, 2],  
                [7, 1, 3, 3, 2],  
                [4, 4, 6, 2, 4],  
                [3, 5, 5, 3, 4]   
            ],
            getPercentData: (typeIndex) => {
                return dataConfig.timeData.map(day => {
                    const total = day.reduce((a,b) => a + b, 0);
                    return Number(((day[typeIndex]/total)*100).toFixed(2));
                })
            }
        };

        const option = {
            tooltip: {
                trigger: 'axis',
                axisPointer: { type: 'shadow' },
                formatter: (params) => {
                    const day = params[0].axisValue;
                    let html = `
                        <div class="tooltip-table">
                            <div class="tooltip-row">
                                <div class="tooltip-cell" style="font-weight:bold;padding-bottom:8px">${day}</div>
                            </div>
                    `;

                    // 生成数据行
                    params.forEach(item => {
                        const isPercent = item.seriesName.includes('占比');
                        const name = isPercent ? 
                            item.seriesName : 
                            `${item.seriesName}`; // 非占比类添加全角冒号
                        
                        const value = isPercent ? 
                            `${item.value.toFixed(2)}%` : 
                            `${item.value}小时`;

                        html += `
                            <div class="tooltip-row">
                                <div class="tooltip-cell name-col">
                                    ${item.marker} ${name}
                                </div>
                                <div class="tooltip-cell value-col">
                                    ${value}
                                </div>
                            </div>
                        `;
                    });

                    html += '</div>';
                    return html;
                }
            },
            legend: {
                data: [...dataConfig.categories, '学习占比', '工作占比'],
                textStyle: { fontSize: 14 }
            },
            xAxis: [{
                type: 'category',
                data: dataConfig.days,
                axisLabel: { 
                    rotate: 45,
                    fontSize: 14
                }
            }],
            yAxis: [
                { 
                    type: 'value',
                    name: '时间(小时)',
                    min: 0,
                    max: 24,
                    axisLabel: { fontSize: 14 }
                },
                { 
                    type: 'value',
                    name: '占比',
                    min: 0,
                    max: 100,
                    axisLabel: { 
                        formatter: '{value}%',
                        fontSize: 14
                    }
                }
            ],
            series: [
                ...dataConfig.categories.map((name, idx) => ({
                    name,
                    type: 'bar',
                    stack: 'time',
                    data: dataConfig.timeData.map(day => day[idx]),
                    itemStyle: {
                        color: ['#5470C6','#91CC75','#FAC858','#EE6666','#73C0DE'][idx]
                    }
                })),
                {
                    name: '学习占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(3),
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: { color: '#EE6666' }
                },
                {
                    name: '工作占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(0),
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: { color: '#5470C6' }
                }
            ]
        };

        chart.setOption(option);
    </script>
</body>
</html>

(2)valueFormatter属性

(2)ECharts的每个系列(series)可以有自己的tooltip配置,特别是valueFormatter属性,用来格式化该系列在Tooltip中的数值显示

  • 柱状图系列通过 valueFormatter 添加 小时 单位
  • 折线图系列通过 valueFormatter 添加 % 符号

在这里插入图片描述

代码示例:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>周时间分布统计</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js"></script>
</head>
<body>
    <div id="main" style="width: 1200px;height:600px;"></div>
    <script>
        const chart = echarts.init(document.getElementById('main'));

        // 数据配置
        const dataConfig = {
            days: ['周一', '周二', '周三', '周四', '周五', '周六', '周日'],
            categories: ['工作', '休息', '娱乐', '学习', '社交'],
            timeData: [
                [8, 2, 3, 2, 1],  
                [9, 1, 2, 2, 2],  
                [7, 3, 2, 3, 1],  
                [8, 2, 2, 2, 2],  
                [7, 1, 3, 3, 2],  
                [4, 4, 6, 2, 4],  
                [3, 5, 5, 3, 4]   
            ],
            getPercentData: (typeIndex) => {
                return dataConfig.timeData.map(day => {
                    const total = day.reduce((a,b) => a + b, 0);
                    return Number(((day[typeIndex]/total)*100).toFixed(2));
                })
            }
        };

        const option = {
            tooltip: {
                trigger: 'axis',
                axisPointer: { type: 'shadow' }
            },
            legend: {
                data: [...dataConfig.categories, '学习占比', '工作占比']
            },
            xAxis: [{
                type: 'category',
                data: dataConfig.days,
                axisLabel: { rotate: 45 }
            }],
            yAxis: [
                { 
                    type: 'value',
                    name: '时间(小时)',
                    min: 0,
                    max: 24
                },
                { 
                    type: 'value',
                    name: '占比',
                    min: 0,
                    max: 100,
                    axisLabel: { formatter: '{value}%' }
                }
            ],
            series: [
                // 堆叠柱状图系列
                ...dataConfig.categories.map((name, idx) => ({
                    name,
                    type: 'bar',
                    stack: 'time',
                    data: dataConfig.timeData.map(day => day[idx]),
                    tooltip: {
                        valueFormatter: value => `${value} 小时` // 时间格式化
                    },
                    itemStyle: {
                        color: ['#5470C6','#91CC75','#FAC858','#EE6666','#73C0DE'][idx]
                    }
                })),
                // 学习占比折线
                {
                    name: '学习占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(3),
                    tooltip: {
                        valueFormatter: value => `${value}%` // 百分比格式化
                    },
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: { color: '#EE6666' }
                },
                // 工作占比折线
                {
                    name: '工作占比',
                    type: 'line',
                    yAxisIndex: 1,
                    data: dataConfig.getPercentData(0),
                    tooltip: {
                        valueFormatter: value => `${value}%` // 百分比格式化
                    },
                    symbol: 'circle',
                    symbolSize: 8,
                    itemStyle: { color: '#5470C6' }
                }
            ]
        };

        chart.setOption(option);
    </script>
</body>
</html>

优化建议

  • 如需更紧凑的显示,可添加全局样式:

    body { font-family: 'Menlo', 'Consolas', monospace; }
    
  • 调整提示框宽度:

    tooltip: {
        trigger: 'axis',
        axisPointer: { type: 'shadow' },
        confine: true, // 防止溢出
        extraCssText: 'width: 240px;' // 固定宽度
    }
    

低功耗蓝牙项目,需要一块懂省电的板

思澈 SF32LB52 芯片,BLE 协议栈深度优化,上手即开发

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值