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

如何在Vega-Lite中创建含自定义文本、图标及页脚注释的KPI可视化

解决Vega-Lite KPI可视化的四个挑战

你的原始代码已经搭好了基础框架,下面针对四个问题逐一调整:

1. 精确定位文本

要在卡片内添加KPI名称、当前值、历史变化等文本,直接在layer里新增text标记,通过x和y的固定值定位,同时绑定对应字段:

{
  "mark": {
    "type": "text",
    "fontSize": 16,
    "fontWeight": "bold"
  },
  "encoding": {
    "x": {"value": 20},
    "y": {"value": 40},
    "text": {"field": "KPI Name"}
  }
},
{
  "mark": {
    "type": "text",
    "fontSize": 24,
    "fontWeight": "bold"
  },
  "encoding": {
    "x": {"value": 20},
    "y": {"value": 70},
    "text": {"field": "Current Value", "format": ".2s"} // 格式化数值,比如百万显示为M
  }
},
{
  "mark": {
    "type": "text",
    "fontSize": 12,
    "fill": "#666"
  },
  "encoding": {
    "x": {"value": 20},
    "y": {"value": 95},
    "text": {"field": "Historical Text"}
  }
}

注:因为用了facet,每个卡片的文本会自动对应各自的数据,无需额外处理。

2. 添加自定义趋势图标及颜色

两种简单实现方式:

  • 用emoji作为图标:新增text标记,根据Trend字段显示不同emoji,同时绑定颜色:
{
  "mark": {
    "type": "text",
    "fontSize": 20
  },
  "encoding": {
    "x": {"value": 350},
    "y": {"value": 50},
    "text": {"calculate": "datum.Trend === 'Increase' ? '▲' : '▼'"},
    "color": {"calculate": "datum.Trend === 'Increase' ? '#2ecc71' : '#e74c3c'"}
  }
}
  • 用自定义形状:如果需要更规范的图标,用shape标记配合符号配置:
{
  "mark": {
    "type": "shape",
    "size": 150
  },
  "encoding": {
    "x": {"value": 350},
    "y": {"value": 50},
    "shape": {"field": "Trend", "scale": {"domain": ["Increase", "Decrease"], "range": ["triangle-up", "triangle-down"]}},
    "color": {"field": "Trend", "scale": {"domain": ["Increase", "Decrease"], "range": ["#2ecc71", "#e74c3c"]}}
  }
}

3. 添加基线和更新日期的页脚注释

在layer底部添加两个text标记,定位到卡片底部区域:

{
  "mark": {
    "type": "text",
    "fontSize": 10,
    "fill": "#666"
  },
  "encoding": {
    "x": {"value": 20},
    "y": {"value": 200}, // 卡片高度219,设置为200靠近底部
    "text": {"field": "Base line text"}
  }
},
{
  "mark": {
    "type": "text",
    "fontSize": 10,
    "fill": "#666"
  },
  "encoding": {
    "x": {"value": 300},
    "y": {"value": 200},
    "text": {"field": "Updated Date"}
  }
}

4. 调整条形间距

两种方法按需选择:

  • 调整条形高度:修改bar标记的size属性,数值越大条形越高,间距越小:
"mark": {
  "type": "bar",
  "size": 25, // 原19,增大后间距变小
  "yOffset": -40
}
  • 调整y轴 padding:在y轴编码里添加padding参数,控制ordinal轴的间距:
"y": {
  "field": "Measure",
  "type": "ordinal",
  "sort": ["Target Value","Current Value"],
  "title": null,
  "padding": 0.8 // 数值越大,条形间距越大
}

修改后的完整代码

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      {"X":1,"Y":1,"KPI Name": "KPI 1", "Target Value": 50, "Current Value": 30, "Base line": 10, "Base line text": "Baseline Value: 10", "Historical Text": "24% Since Jun", "Updated Date": "Update 23 Jul 2024","Trend": "Increase"},
      {"X":2,"Y":1,"KPI Name": "KPI 2", "Target Value": 50, "Current Value": 30, "Base line": 10, "Base line text": "Baseline Value: 10", "Historical Text": "24%  Since Jun", "Updated Date": "Update 23 Jul 2024","Trend": "Increase"},
      {"X":3,"Y":1,"KPI Name": "KPI 3", "Target Value": 5000000, "Current Value": 3000000, "Base line": 1000000, "Base line text": "Baseline Value: 1000000", "Historical Text": "24%  Since Jun", "Updated Date": "Update 23 Jul 2024","Trend": "Increase"},
      {"X":1,"Y":2,"KPI Name": "KPI 4", "Target Value": 0.9, "Current Value": 0.6, "Base line": 0.2, "Base line text": "Baseline Value: 10%", "Historical Text": "24%  Since Jun", "Updated Date": "Update 23 Jul 2024","Trend": "Increase"}
    ]
  },
  "transform": [
    {"fold": ["Current Value", "Target Value"], "as": ["Measure", "Value"]},
    {"calculate": "min(datum['Target Value'],datum['Current Value'],0)", "as": "start_value"},
    {"calculate": "max(datum['Target Value'],datum['Current Value'])" , "as": "max_value"},
    {"calculate": "datum.max_value+(0.27*datum.max_value)","as": "end_value"}
  ],
  "facet": {
    "row": {"field": "Y", "header":null},
    "column": {"field": "X", "header":null}
  },
  "spec": {
    "width": 393,
    "height": 219,
    "encoding": {
      "x": {"type": "quantitative", "scale": {"nice": false}, "title": null, "axis": null}
    },
    "layer":[
      {
        "mark": {
          "type": "rect",
          "width": 393,
          "height": 219,
          "fill": "#ffffff",
          "stroke": "#000000",
          "strokeWidth": 1,
          "cornerRadius": 4
        },
        "encoding": {
          "x": {"value": 0},
          "y": {"value": 0}
        }
      },
      {
        "mark": {
          "type": "bar",
          "size": 25,
          "yOffset": -40
        },
        "encoding": {
          "y": {
            "field": "Measure",
            "type": "ordinal",
            "sort":["Target Value","Current Value"],
            "title":null,
            "padding": 0.5
          },
          "x": {
            "field": "Value",
            "type": "quantitative",
            "title": null,
            "axis": null,
            "scale":{"domain": {"data": "", "fields": ["start_value", "end_value"]}}
          },
          "color": {
            "field": "Measure",
            "type": "nominal",
            "title": null,
            "legend":null,
            "scale": {"domain": ["Current Value", "Target Value"], "range": ["#3498db", "#bdc3c7"]}
          }
        }
      },
      // KPI名称
      {
        "mark": {"type": "text", "fontSize": 16, "fontWeight": "bold"},
        "encoding": {
          "x": {"value": 20},
          "y": {"value": 40},
          "text": {"field": "KPI Name"}
        }
      },
      // 当前值
      {
        "mark": {"type": "text", "fontSize": 24, "fontWeight": "bold"},
        "encoding": {
          "x": {"value": 20},
          "y": {"value": 70},
          "text": {"field": "Current Value", "format": ".2s"}
        }
      },
      // 历史变化文本
      {
        "mark": {"type": "text", "fontSize": 12, "fill": "#666"},
        "encoding": {
          "x": {"value": 20},
          "y": {"value": 95},
          "text": {"field": "Historical Text"}
        }
      },
      // 趋势图标
      {
        "mark": {"type": "text", "fontSize": 20},
        "encoding": {
          "x": {"value": 350},
          "y": {"value": 50},
          "text": {"calculate": "datum.Trend === 'Increase' ? '▲' : '▼'"},
          "color": {"calculate": "datum.Trend === 'Increase' ? '#2ecc71' : '#e74c3c'"}
        }
      },
      // 基线注释
      {
        "mark": {"type": "text", "fontSize": 10, "fill": "#666"},
        "encoding": {
          "x": {"value": 20},
          "y": {"value": 200},
          "text": {"field": "Base line text"}
        }
      },
      // 更新日期
      {
        "mark": {"type": "text", "fontSize": 10, "fill": "#666"},
        "encoding": {
          "x": {"value": 300},
          "y": {"value": 200},
          "text": {"field": "Updated Date"}
        }
      }
    ]
  },
  "resolve": {
    "axis": {"x": "independent", "y": "independent"},
    "scale": {"x": "independent"}
  },
  "config": {
    "facet": {"spacing": 48}
  }
}

内容的提问来源于stack exchange,提问作者Gurava Raju

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 04:10:54