You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现ECharts Graphic组件内文本的容器尺寸响应式适配?

如何实现ECharts Graphic组件内文本的容器尺寸响应式适配?

我看你已经把自定义的vBox容器弄成响应式的了,就差里面的文本跟着容器同步适配对吧?其实核心问题就是你之前的文本配置和容器尺寸没完全绑定上——比如resize时文本宽度用了整个图表的宽度,和容器宽度脱节了。我来帮你调整代码,让文本的所有尺寸都跟着容器走,不管是截断省略还是自动换行都能正常工作:

核心适配思路

  • 文本的可用宽度必须和vBox容器的实时宽度绑定(可以留适当内边距避免贴边),不能用整个图表的宽度
  • 字号、行高这些文本样式,也要基于容器的宽高计算,而不是图表整体尺寸
  • 把初始化和resize时的配置逻辑抽成统一函数,避免两套不同计算逻辑导致适配错位

修改后的完整代码

JavaScript 部分

document.addEventListener("DOMContentLoaded", () => {
    // 自定义圆角矩形组件
    const valueBox = echarts.graphic.extendShape({
        type: "vBox",
        shape: {
            r: 5
        },
        style: {
            lineWidth: .5,
            stroke: "#000",
            lineDash: 'solid',
            shadowBlur: 7.5,
            shadowColor: '#000', 
            shadowOffsetX: 3,
            shadowOffsetY: 3
        },
        buildPath: (ctx, shape) => {
            echarts.graphic.Rect.prototype.buildPath.call(this, ctx, shape);
        }
    });

    // 注册自定义形状
    echarts.graphic.registerShape("vBox", valueBox);

    // 初始化ECharts实例
    const chartUse = echarts.init(document.getElementsByClassName("chart")[0]);

    // 抽离统一的配置生成函数,避免重复逻辑
    function getGraphicConfig(chartWidth, chartHeight) {
        // 计算vBox容器的实时尺寸
        const boxWidth = chartWidth / 5;
        const boxHeight = chartHeight / 5;
        // 文本可用宽度:容器宽度的85%,留15%内边距避免贴边
        const textAvailableWidth = boxWidth * 0.85;
        
        // 基于容器尺寸计算文本样式
        const textBaseStyle = {
            rich: {
                text: {
                    lineHeight: boxHeight / 4, // 行高适配容器高度
                    fill: '#000',
                    fontSize: boxWidth / 14 // 字号基于容器宽度计算,更精准
                }
            }
        };

        return {
            graphic: [
                {
                    type: "group",
                    children: [
                        {
                            type: 'vBox',
                            shape: {
                                x: (chartWidth - boxWidth) / 2, // 水平居中
                                y: (chartHeight - boxHeight) / 2, // 垂直居中
                                width: boxWidth,
                                height: boxHeight,
                                r: 5
                            },
                            style: {
                                fill: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
                                    { offset: .5, color: "#fafac0" },
                                    { offset: 1, color: "#008cba" }
                                ]),
                                lineCap: "x",
                                lineWidth: 2,
                                stroke: '#000'
                            },
                            textContent: {
                                // 可切换两种适配模式:
                                // 模式1:文本超出截断并显示省略号
                                overflow: 'truncate',
                                ellipsis: '...',
                                // 模式2:文本超出自动换行
                                // overflow: 'break',
                                width: textAvailableWidth,
                                align: "center",
                                style: {
                                    text: "{text|Overflowwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww\n50%}",
                                    ...textBaseStyle
                                }
                            },
                            textConfig: {
                                position: "inside"
                            }
                        }
                    ]
                }
            ]
        };
    }

    // 首次渲染图表
    function initChart() {
        const [chartWidth, chartHeight] = [chartUse.getWidth(), chartUse.getHeight()];
        const option = getGraphicConfig(chartWidth, chartHeight);
        chartUse.setOption(option);
    }

    // 监听窗口resize事件,实时更新配置
    window.addEventListener("resize", () => {
        chartUse.resize();
        const [chartWidth, chartHeight] = [chartUse.getWidth(), chartUse.getHeight()];
        const option = getGraphicConfig(chartWidth, chartHeight);
        chartUse.setOption(option);
    });

    // 启动初始化
    initChart();
});

HTML 部分

<head>
    <script src="https://cdn.jsdelivr.net/npm/echarts@5.6.0/dist/echarts.min.js"></script>
    <title>Custom Shape Example</title>
</head>

<div class="chart" style="width: 100%; height: 100vh;"></div>

关键修改点说明

  1. 统一配置逻辑:把初始化和resize时的配置生成逻辑抽成getGraphicConfig函数,确保两种场景下的计算逻辑完全一致,不会出现适配错位
  2. 文本宽度绑定容器:文本的width现在基于vBox容器宽度计算(留15%内边距),彻底解决了之前resize时文本宽度和容器脱节的问题
  3. 文本样式适配容器:字号、行高都改成基于容器的宽高计算,比原来用整个图表尺寸更精准,确保文本在容器内的显示比例始终协调
  4. 双模式切换便捷:只需要修改textContent里的overflow属性,就能在“截断省略”和“自动换行”两种模式间切换,其他配置无需改动

这样修改后,不管是拖动窗口调整大小,还是用Ctrl+/Ctrl-缩放页面,文本都会跟着vBox容器的尺寸实时适配,再也不会出现文本超出容器或者留白过多的问题。

备注:内容来源于stack exchange,提问作者neves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 12:48:06