Layui怎样实现在表格单元格内嵌入简易图表

作者:袖梨 2026-07-23
Layui表格单元格内嵌柱状图需用templet自定义SVG:内联绘制rect,宽6px、高动态计算(min(score×2,80)),y=20−height实现底对齐,加vertical-align:middle防错位;禁用echarts以防内存溢出;负值需分向绘制并归一化处理。

表格单元格里直接画柱状图?Layui原生不支持,得自己“塞进去”

Layui 的 table.render() 不提供单元格内图表渲染能力,所谓“嵌入图表”,本质是利用 templet 自定义模板,在单元格 HTML 中插入 SVG 或 Canvas,再用轻量级绘图逻辑(如纯 JS 绘制或借用 tiny chart 库)生成简易可视化。别指望调个配置就出图——得手写渲染逻辑。

templet 插入 SVG 柱状图最可控

比 Canvas 更轻、更易缩放、无像素模糊,且可直接用 CSS 控制颜色和尺寸。关键点在于:SVG 必须内联写在模板里,不能异步加载;宽度高度需根据数据动态计算,避免溢出单元格。

  • cols 配置中为对应列设置 templet: function(d) { return "<svg>...</svg>"; }
  • 柱子宽度固定为 6px,总宽度按 Math.min(d.value * 2, 80) 限制,防止撑破单元格
  • <rect> 绘制单柱,y 值从 20 - height 开始,实现底部对齐
  • 务必加 style="vertical-align: middle;"<svg>,否则图文基线错位
templet: function(d) {  const w = Math.min(d.score * 2, 80);  return '<svg width="80" height="20" style="vertical-align:middle">' +         '<rect x="0" y="' + (20 - w) + '" width="6" height="' + w + '" fill="#5FB878"/>' +         '</svg> ' + d.score;}

echarts 小图?小心内存和重绘开销

每个单元格都 new 一个 echarts.init() 实例,100 行表格就会创建 100 个实例,滚动时极易卡顿、内存暴涨。只建议在行数 ≤ 20 且图表非必需交互的场景下谨慎使用。

  • 必须复用 DOM 容器:为每行分配唯一 id,如 "chart-+d.id",并在 templet 中返回带 id 的 <div>
  • 渲染逻辑必须延迟到 table.on('rendered') 后执行,否则 DOM 还没挂载
  • 每次重新渲染表格前,要手动调用 echarts.getInstanceByDom(...).dispose() 清理旧实例
  • 配置极度精简:关掉 tooltip、legend、animation,series 只留一个 bar,grid 设为 {left:0,top:0,right:0,bottom:0}

数值太小或为负数时图表会“消失”?得做归一化兜底

原始值如 0.3-5 直接映射成像素高度,会导致柱子不可见或坐标越界。必须统一映射到 [0, 1] 区间再放大,且负值需特殊处理(比如用红色反向绘制,或转为绝对值+标注符号)。

  • 推荐用 min-max 归一化:norm = (val - minVal) / (maxVal - minVal + 1e-6),再乘以最大显示高度(如 18)
  • 若列中存在负值,建议拆成两段:正数向上画,负数向下画(y 起点设为 10,height 为 Math.abs(val) * scale),并用不同 fill
  • 值为 0 时,至少保留 1px 高度或显示短横线,避免视觉“空缺”误导

真正难的不是画一根柱子,而是让上百个单元格里的图表响应一致、不打架、不泄漏、不拖慢页面——所有动态计算都要在 templet 函数里完成,不能依赖外部状态或异步回调。

相关文章

精彩推荐