Vega图例元素右侧出现额外内边距问题求助
Vega生成SVG时图例右侧额外内边距问题
我用给定的JSON在Vega编辑器里渲染图表显示正常,但通过代码生成SVG时,图例元素右侧出现了额外内边距:


实现代码
const vega = require('vega'); module.exports = async function (context, req) { try { const vview = await new vega.View(vega.parse(req.body), { renderer: 'none' }); let svg = await vview.toSVG(); context.res = { body: svg, contentType: 'image/svg+xml' }; } catch (error) { context.log(`Error during rendering vega chart: ${error}.`); throw error; } }
req.body包含图表定义的JSON,尝试过文档中的所有选项都无法控制该内边距,求解决方法。
图表定义JSON
{ "$schema": "https://vega.github.io/schema/vega/v5.json", "description": "Sample", "width": 600, "height": 300, "autosize": { "type": "fit", "contains": "padding" }, "padding": 10, "data": [ { "name": "table", "values": [ { "category": "Portfolio", "year": 2020, "section": "vor 1900", "volume": 0.04 }, { "category": "Portfolio", "year": 2020, "section": "1900-1950", "volume": 0.07 }, { "category": "Portfolio", "year": 2020, "section": "1950-1970", "volume": 0.13 }, { "category": "Portfolio", "year": 2020, "section": "1970-1990", "volume": 0.19 }, { "category": "Portfolio", "year": 2020, "section": "1990-2010", "volume": 0.24 }, { "category": "Portfolio", "year": 2020, "section": "nach 2010", "volume": 0.33 }, { "category": "Portfolio", "year": 2021, "section": "vor 1900", "volume": 0.03 }, { "category": "Portfolio", "year": 2021, "section": "1900-1950", "volume": 0.06 }, { "category": "Portfolio", "year": 2021, "section": "1950-1970", "volume": 0.11 }, { "category": "Portfolio", "year": 2021, "section": "1970-1990", "volume": 0.19 }, { "category": "Portfolio", "year": 2021, "section": "1990-2010", "volume": 0.25 }, { "category": "Portfolio", "year": 2021, "section": "nach 2010", "volume": 0.36 }, { "category": "Benchmark", "year": 2020, "section": "vor 1900", "volume": 0.06 }, { "category": "Benchmark", "year": 2020, "section": "1900-1950", "volume": 0.09 }, { "category": "Benchmark", "year": 2020, "section": "1950-1970", "volume": 0.15 }, { "category": "Benchmark", "year": 2020, "section": "1970-1990", "volume": 0.23 }, { "category": "Benchmark", "year": 2020, "section": "1990-2010", "volume": 0.25 }, { "category": "Benchmark", "year": 2020, "section": "nach 2010", "volume": 0.22 }, { "category": "Benchmark", "year": 2021, "section": "vor 1900", "volume": 0.05 }, { "category": "Benchmark", "year": 2021, "section": "1900-1950", "volume": 0.09 }, { "category": "Benchmark", "year": 2021, "section": "1950-1970", "volume": 0.14 }, { "category": "Benchmark", "year": 2021, "section": "1970-1990", "volume": 0.24 }, { "category": "Benchmark", "year": 2021, "section": "1990-2010", "volume": 0.25 }, { "category": "Benchmark", "year": 2021, "section": "nach 2010", "volume": 0.23 } ], "transform": [ { "type": "stack", "groupby": ["category","year"], "field": "volume" }, { "type": "formula", "as": "colorParam", "expr": "datum.section+' '+datum.category" }, { "type": "formula", "as": "volumePerc", "expr": "format(datum.volume,'.0%')" } ] } ], "signals": [ { "name": "sfont", "value" : "Arial Narrow, serif"}, { "name": "sfontBold", "value" : "Arial Black, serif"}, { "name": "sfontSize", "value" : 16}, { "name": "sfontColor", "value" : "#595959"} ], "scales": [ { "name": "xCategoryScale", "type": "band", "domain": { "data": "table", "field": "category" }, "range": "width" }, { "name": "yscale", "type": "linear", "domain": [0,1], "range": "height", "nice": true }, { "name": "colorScale", "type": "ordinal", "domain": { "data": "table", "field": "colorParam" }, "range": [ "#172431", "#426990", "#638EB9", "#8BABCB", "#BFD1E3", "#D7E2ED", "#322B22", "#6F5F4D", "#958069", "#AE9D8B", "#D3C9BF", "#F1EEEB" ] }, { "name": "legendColorScale", "type": "ordinal", "domain": [ "nach 2010", "1990-2010", "1970-1990", "1950-1970", "1900-1950", "vor 1900" ], "range": [ "#d9d9d9", "#bfbfbf", "#a6a6a6", "#7f7f7f", "#595959", "#262626" ] } ], "axes": [ { "orient": "left", "scale": "yscale", "tickCount": 6, "grid": true, "title": "m²EBF-%", "titleX":-40, "titleFontSize": {"signal": "sfontSize"}, "titleFont": {"signal": "sfont"}, "titleColor":{"signal": "sfontColor"}, "titleFontWeight": "normal", "labelFontSize": {"signal": "sfontSize"}, "labelFont": {"signal": "sfont"}, "labelColor":{"signal": "sfontColor"}, "encode": { "labels": { "update": { "text": {"signal": "format(datum.value, '.0%')"} } } } }, { "orient": "bottom", "scale": "xCategoryScale", "tickBand": "extent", "tickSize": 50, "titleFontSize": {"signal": "sfontSize"}, "titleFont": {"signal": "sfont"}, "titleColor":{"signal": "sfontColor"}, "titleFontWeight": "normal", "labelFontSize": {"signal": "sfontSize"}, "labelFont": {"signal": "sfont"}, "labelColor":{"signal": "sfontColor"}, "encode": { "labels": { "update": { "dy": { "value": -20 } } } } } ], "legends": [{ "type": "symbol", "fill": "legendColorScale", "symbolType": "square", "orient":"right", "legendX": {"signal": "width", "offset": 20}, "legendY": {"signal": "height / 2", "offset":-40}, "labelFontSize": {"signal": "sfontSize"}, "labelFont": {"signal": "sfont"}, "labelColor":{"signal": "sfontColor"} }], "marks": [ { "name": "categories", "type": "group", "from": { "facet": { "data": "table", "name": "perCategory", "groupby": "category" } }, "encode": { "enter": { "x": { "scale": "xCategoryScale", "field": "category" }, "width": { "scale": "xYearScale", "band": 1 }, "y": { "scale": "yscale", "field": "volume" }, "y2": { "scale": "yscale", "value": 0 } } }, "signals": [ { "name": "width", "update": "bandwidth('xCategoryScale')" } ], "scales": [ { "name": "xYearScale", "type": "band", "range": "width", "domain": { "data": "perCategory", "field": "year" }, "padding": 0.06 } ], "axes": [ { "orient": "bottom", "scale": "xYearScale", "zindex": 1, "offset": {"signal": "height"}, "tickSize":{"value": 0}, "labelFontSize": {"signal": "sfontSize"}, "labelFont": {"signal": "sfont"}, "labelColor":{"signal": "sfontColor"}, "encode": { "labels": { "update": { "dy" : {"value": 5} } } } } ], "marks": [ { "name": "volumeBars", "from": { "data": "perCategory"}, "type": "rect", "encode": { "enter": { "x": { "scale": "xYearScale", "field": "year", "band": 0.3 }, "width": { "scale": "xYearScale", "band": 0.4 }, "y": { "scale": "yscale", "field": "y0" }, "y2": { "scale": "yscale", "field": "y1" }, "fill": { "scale": "colorScale", "signal": "datum.colorParam" } } } }, { "name": "barLabel", "type": "text", "from": { "data": "volumeBars" }, "encode": { "enter": { "y": { "field": "y", "offset": { "field": "height", "mult":0.5 } }, "x": { "field": "x", "offset": { "field": "width", "mult": 0.5 } }, "stroke":{"value": "white"}, "strokeWidth":{"value": 0.4}, "fontSize": {"signal": "sfontSize"}, "font": {"signal": "sfontBold"}, "color":{"signal": "sfontColor"}, "baseline":{"value": "middle"}, "fill":{"value": "black"}, "align": [ { "test": "indexof(data('volumeBars'), datum) % 2 == 0", "value": "right" }, { "value": "left" } ], "text": { "field": "datum.volumePerc" } } } } ] } ] }
解决方法
- 限制标签宽度:在图例配置中添加
labelLimit属性,明确约束标签宽度,避免自动扩展产生多余空间:"legends": [{ // 原有配置 "labelLimit": 100 // 根据实际标签长度调整数值 }] - 调整图例内边距:直接设置图例的
padding属性,控制内部边距:"legends": [{ // 原有配置 "padding": 0 // 按需设置数值,减少右侧冗余空间 }] - SVG后处理:如果上述方法无效,可在生成SVG后通过字符串替换移除多余样式:
let svg = await vview.toSVG(); // 替换图例组的padding属性 svg = svg.replace(/<g class="legend"[^>]*>/g, (match) => { return match.replace(/padding="[^"]*"/, 'padding="0"'); });
内容的提问来源于stack exchange,提问作者Dawid Rutkowski
相关产品推荐
相关产品推荐

