使用此规范,我尝试创建一个实际与预算图表,其中值打印在条形上方的同一级别。我怀疑更好的方法会涉及图层,但目前我已经尝试添加最大 y 值的倍数并将文本标记放在那里。当您只有 2 个标记但第三个标记无法与顶部/底部对齐并因此永远无法正确渲染时,它可以正常工作。我唯一取得的部分成功是明确设置文本标记的 y 坐标。似乎偏移量也被忽略了。
我的最终目标是制作类似于本视频中的子弹图的东西 https://www.youtube.com/watch?v=Tc0D0THMI78 但对于条形上方的文本值...非常感谢任何指导。
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Overlapping bar chart showing monthly actual vs budget values for 2024.",
"width": 550,
"height": {"signal": "chartHeight"},
"padding": 5,
"signals": [
{
"name": "maxY3",
"update": "max(actualExtent[1], budgetExtent[1])*1.4"
},
{
"name": "chartHeight",
"update": "200"
}
],
"data": [
{
"name": "table",
"values": [
{"date": "2024-01-01", "actual": 100000000, "budget": 150000000},
{"date": "2024-02-01", "actual": 120000000, "budget": 120000000},
{"date": "2024-03-01", "actual": 140000000, "budget": 130000000},
{"date": "2024-04-01", "actual": 160000000, "budget": 170000000},
{"date": "2024-05-01", "actual": 180000000, "budget": 110000000},
{"date": "2024-06-01", "actual": 220000000, "budget": 210000000},
{"date": "2024-07-01", "actual": 240000000, "budget": 230000000},
{"date": "2024-08-01", "actual": 260000000, "budget": 250000000},
{"date": "2024-09-01", "actual": 280000000, "budget": 220000000},
{"date": "2024-10-01", "actual": 300000000, "budget": 320000000},
{"date": "2024-11-01", "actual": 350000000, "budget": 340000000},
{"date": "2024-12-01", "actual": 370000000, "budget": 360000000}
],
"transform": [
{
"type": "formula",
"expr": "timeParse(datum.date, '%Y-%m-%d')",
"as": "parsedDate"
},{
"type": "formula",
"expr": "datum.actual-datum.budget",
"as": "variance"
},{
"type": "formula",
"expr": "datum.budget!=0?datum.variance/datum.budget:0",
"as": "variancepct"
},
{
"type": "extent",
"field": "actual",
"signal": "actualExtent"
},
{
"type": "extent",
"field": "budget",
"signal": "budgetExtent"
}
]
}
],
"scales": [
{
"name": "x",
"type": "time",
"domain": {"data": "table", "field": "parsedDate"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"domain": [0, {"signal": "maxY3"}],
"range": "height",
"nice": true
}
],
"axes": [
{
"orient": "bottom",
"scale": "x",
"format": "%b",
"title": "Month",
"ticks": true,
"labelAlign": "center",
"tickOffset": 20
},
{
"orient": "left",
"scale": "y",
"title": "",
"domain": false,
"labels": false,
"grid": false,
"ticks":false
}
],
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 0},
"width": {"value": 30},
"y": {"scale": "y", "field": "actual"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "grey"},
"tooltip": {"signal": "{'Date': timeFormat(datum.parsedDate, '%B'), 'Actual': format(datum.actual, ',')}"}
}
}
},
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 10},
"width": {"value": 30},
"y": {"scale": "y", "field": "budget"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "lightblue"},
"tooltip": {"signal": "{'Date': timeFormat(datum.parsedDate, '%B'), 'Budget': format(datum.budget, ',')}"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 20},
"y": {"scale": "y", "value": {"signal": "maxY3"}, "offset":0},
"text": {"signal": "[format(datum.actual,'.4s')]"},
"fontSize": {"value": 14},
"fill": {"value": "black"},
"align": {"value": "center"},
"baseline": {"value": "bottom"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset":20},
"y": {"scale": "y", "value": {"signal": "maxY3"}, "offset":0},
"text": {"signal": "[format(datum.budget,'.4s')]"},
"fontSize": {"value": 14},
"fill": {"value": "black"},
"align": {"value": "center"},
"baseline": {"value": "top"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset":20},
"y": {"scale": "y", "value": {"signal": "maxY3"}, "offset":0},
"text": {"signal": "[format(datum.variancepct,'.2p')]"},
"fontSize": {"value": 14},
"fill": {"value": "black"},
"align": {"value": "center"},
"baseline": {"value": "top"}
}
}
}
]
}
在发布问题并在下面做出有关最佳实践的评论后,我进行了以下编辑,这些编辑几乎让我达到了此时我想去的地方,但我仍然想对该方法进行批评
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Overlapping bar chart showing monthly actual vs budget values for 2024.",
"width": 550,
"height": {"signal": "chartHeight"},
"title": "my generic chart title",
"padding": 5,
"signals": [{
"name": "maxY4",
"update": "max(actualExtent[1], budgetExtent[1])*1.4"
},{
"name": "maxY1",
"update": "max(actualExtent[1], budgetExtent[1])*1.3"
},
{
"name": "maxY2",
"update": "max(actualExtent[1], budgetExtent[1])*1.2"
}, {
"name": "maxY3",
"update": "max(actualExtent[1], budgetExtent[1])*1.1"
},
{
"name": "chartHeight",
"update": "200"
}
],
"data": [
{
"name": "table",
"values": [
{"date": "2024-01-01", "actual": 100000000, "budget": 150000000},
{"date": "2024-02-01", "actual": 120000000, "budget": 120000000},
{"date": "2024-03-01", "actual": 140000000, "budget": 130000000},
{"date": "2024-04-01", "actual": 160000000, "budget": 170000000},
{"date": "2024-05-01", "actual": 180000000, "budget": 110000000},
{"date": "2024-06-01", "actual": 220000000, "budget": 210000000},
{"date": "2024-07-01", "actual": 240000000, "budget": 230000000},
{"date": "2024-08-01", "actual": 260000000, "budget": 250000000},
{"date": "2024-09-01", "actual": 280000000, "budget": 220000000},
{"date": "2024-10-01", "actual": 300000000, "budget": 320000000},
{"date": "2024-11-01", "actual": 350000000, "budget": 340000000},
{"date": "2024-12-01", "actual": 370000000, "budget": 360000000}
],
"transform": [
{
"type": "formula",
"expr": "timeParse(datum.date, '%Y-%m-%d')",
"as": "parsedDate"
},{
"type": "formula",
"expr": "datum.actual-datum.budget",
"as": "variance"
},{
"type": "formula",
"expr": "datum.budget!=0?datum.variance/datum.budget:0",
"as": "variancepct"
},{
"type": "formula",
"expr": "datum.variance>=0 ?1:0",
"as": "isgreen"
},
{
"type": "extent",
"field": "actual",
"signal": "actualExtent"
},
{
"type": "extent",
"field": "budget",
"signal": "budgetExtent"
}
]
}
],
"scales": [
{
"name": "x",
"type": "time",
"domain": {"data": "table", "field": "parsedDate"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"domain": [0, {"signal": "maxY3"}],
"range": "height",
"nice": true
}
],
"axes": [
{
"orient": "bottom",
"scale": "x",
"format": "%b",
"title": "Month",
"ticks": true,
"labelAlign": "center",
"tickOffset": 20
},
{
"orient": "left",
"scale": "y",
"title": "",
"domain": false,
"labels": false,
"grid": false,
"ticks":false
}
],
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 0},
"width": {"value": 30},
"y": {"scale": "y", "field": "budget"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "grey"},
"tooltip": {"signal": "{'Date': timeFormat(datum.parsedDate, '%B'), 'Actual': format(datum.actual, ',')}"}
}
}
},
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 10},
"width": {"value": 30},
"y": {"scale": "y", "field": "actual"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "lightblue"},
"tooltip": {"signal": "{'Date': timeFormat(datum.parsedDate, '%B'), 'Budget': format(datum.budget, ',')}"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 20},
"y": {"scale": "y", "signal": "maxY1", "offset": 0},
"text": {"signal": "[format(datum.actual,'.4s')]"},
"fontSize": {"value": 12},
"fill": {"value": "black"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset":20},
"y": {"scale": "y", "signal": "maxY2", "offset": 0},
"text": {"signal": "[format(datum.budget,'.4s')]"},
"fontSize": {"value": 12},
"fill": {"value": "black"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset":20},
"y": {"scale": "y", "signal": "maxY3", "offset": 0},
"text": {"signal": "[format(datum.variancepct,'.2p')]"},
"fontSize": {"value": 12},
"fill": {"value": "black"},
"align": {"value": "center"} ,
"fill": {
"signal": "datum.isgreen==1?'green':'red'"
}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset":20},
"y": {"scale": "y", "signal": "maxY4", "offset": 0},
"text": {"signal": "[timeFormat(datum.parsedDate, '%b')]"},
"fontSize": {"value": 12},
"fontWeight":{"value":"bold"},
"fill": {"value": "black"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"x": {"value": -10},
"y": {"scale": "y", "signal": "maxY1", "offset": 0},
"text": {"value": "Actual"},
"fontSize": {"value": 12},
"fontWeight":{"value":"bold"},
"fill": {"value": "black"},
"align": {"value": "right"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"x": {"value": -10},
"y": {"scale": "y", "signal": "maxY2", "offset": 0},
"text": {"value": "Budget"},
"fontSize": {"value": 12},
"fontWeight":{"value":"bold"},
"fill": {"value": "black"},
"align": {"value": "right"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"x": {"value": -10},
"y": {"scale": "y", "signal": "maxY3", "offset": 0},
"text": {"value": "Variance %"},
"fontWeight":{"value":"bold"},
"fontSize": {"value": 12},
"fill": {"value": "black"},
"align": {"value": "right"}
}
}
},
{
"type": "text",
"encode": {
"enter": {
"x": {"value": -10},
"y": {"scale": "y", "signal": "maxY4", "offset": 0},
"text": {"value": "Month"},
"fontSize": {"value": 12},
"fontWeight":{"value":"bold"},
"fill": {"value": "black"},
"align": {"value": "right"}
}
}
}
]
}
通过制作数据集,您可以减少文本标记,但在其他方面看起来不错。
{
"$schema": "https://vega.github.io/schema/vega/v5.json",
"description": "Overlapping bar chart showing monthly actual vs budget values for 2024.",
"width": 550,
"height": {"signal": "chartHeight"},
"title": "my generic chart title",
"padding": 5,
"signals": [
{"name": "maxY4", "update": "max(actualExtent[1], budgetExtent[1])*1.4"},
{"name": "maxY1", "update": "max(actualExtent[1], budgetExtent[1])*1.3"},
{"name": "maxY2", "update": "max(actualExtent[1], budgetExtent[1])*1.2"},
{"name": "maxY3", "update": "max(actualExtent[1], budgetExtent[1])*1.1"},
{"name": "chartHeight", "update": "200"}
],
"data": [
{
"name": "table",
"values": [
{"date": "2024-01-01", "actual": 100000000, "budget": 150000000},
{"date": "2024-02-01", "actual": 120000000, "budget": 120000000},
{"date": "2024-03-01", "actual": 140000000, "budget": 130000000},
{"date": "2024-04-01", "actual": 160000000, "budget": 170000000},
{"date": "2024-05-01", "actual": 180000000, "budget": 110000000},
{"date": "2024-06-01", "actual": 220000000, "budget": 210000000},
{"date": "2024-07-01", "actual": 240000000, "budget": 230000000},
{"date": "2024-08-01", "actual": 260000000, "budget": 250000000},
{"date": "2024-09-01", "actual": 280000000, "budget": 220000000},
{"date": "2024-10-01", "actual": 300000000, "budget": 320000000},
{"date": "2024-11-01", "actual": 350000000, "budget": 340000000},
{"date": "2024-12-01", "actual": 370000000, "budget": 360000000}
],
"transform": [
{
"type": "formula",
"expr": "timeParse(datum.date, '%Y-%m-%d')",
"as": "parsedDate"
},
{
"type": "formula",
"expr": "datum.actual-datum.budget",
"as": "variance"
},
{
"type": "formula",
"expr": "datum.budget!=0?datum.variance/datum.budget:0",
"as": "variancepct"
},
{"type": "formula", "expr": "datum.variance>=0 ?1:0", "as": "isgreen"},
{"type": "extent", "field": "actual", "signal": "actualExtent"},
{"type": "extent", "field": "budget", "signal": "budgetExtent"}
]
},
{
"name": "headers",
"values": [
{"id": 1, "val": "Month"},
{"id": 2, "val": "Actual"},
{"id": 3, "val": "Budget"},
{"id": 4, "val": "Variance %"}
]
}
],
"scales": [
{
"name": "x",
"type": "time",
"domain": {"data": "table", "field": "parsedDate"},
"range": "width"
},
{
"name": "y",
"type": "linear",
"domain": [0, {"signal": "maxY3"}],
"range": "height",
"nice": true
}
],
"axes": [
{
"orient": "bottom",
"scale": "x",
"format": "%b",
"title": "Month",
"ticks": true,
"labelAlign": "center",
"tickOffset": 20
},
{
"orient": "left",
"scale": "y",
"title": "",
"domain": false,
"labels": false,
"grid": false,
"ticks": false
}
],
"marks": [
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 0},
"width": {"value": 30},
"y": {"scale": "y", "field": "budget"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "grey"},
"tooltip": {
"signal": "{'Date': timeFormat(datum.parsedDate, '%B'), 'Actual': format(datum.actual, ',')}"
}
}
}
},
{
"type": "rect",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 10},
"width": {"value": 30},
"y": {"scale": "y", "field": "actual"},
"y2": {"scale": "y", "value": 0},
"fill": {"value": "lightblue"},
"tooltip": {
"signal": "{'Date': timeFormat(datum.parsedDate, '%B'), 'Budget': format(datum.budget, ',')}"
}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 20},
"y": {"scale": "y", "signal": "maxY1", "offset": 0},
"text": {"signal": "[format(datum.actual,'.4s')]"},
"fontSize": {"value": 12},
"fill": {"value": "black"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 20},
"y": {"scale": "y", "signal": "maxY2", "offset": 0},
"text": {"signal": "[format(datum.budget,'.4s')]"},
"fontSize": {"value": 12},
"fill": {"value": "black"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 20},
"y": {"scale": "y", "signal": "maxY3", "offset": 0},
"text": {"signal": "[format(datum.variancepct,'.2p')]"},
"fontSize": {"value": 12},
"fill": {"signal": "datum.isgreen==1?'green':'red'"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"from": {"data": "table"},
"encode": {
"enter": {
"x": {"scale": "x", "field": "parsedDate", "offset": 20},
"y": {"scale": "y", "signal": "maxY4", "offset": 0},
"text": {"signal": "[timeFormat(datum.parsedDate, '%b')]"},
"fontSize": {"value": 12},
"fontWeight": {"value": "bold"},
"fill": {"value": "black"},
"align": {"value": "center"}
}
}
},
{
"type": "text",
"name": "aa",
"from": {"data": "headers"},
"encode": {
"update": {
"x": {"value": -10},
"y": {
"scale": "y",
"signal": "datum.id == 1?maxY4:datum.id == 2?maxY1:datum.id == 3?maxY2:maxY3"
},
"text": {"field": "val"},
"fontSize": {"value": 12},
"fontWeight": {"value": "bold"},
"fill": {"value": "black"},
"align": {"value": "right"}
}
}
}
]
}