缩放和居中 D3-Graphviz 图
Scale and Center D3-Graphviz Graph
使用 d3-graphviz 缩放和居中图形的最佳方法是什么?我希望我可以使用 scale(0.5)
但这会使生成的图形不居中。
我可能会使用 .attributer()
并手动调整 <svg>
和 <g>
元素以获得我正在寻找的内容,但我认为可能有更好的方式?
d3.select("#graph")
.graphviz()
.width(300)
.height(300)
.fit(true)
.scale(.5)
.renderDot('digraph {a -> b}');
<script src="//d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="width: 300px; height: 300px; border: 1px solid black"></div>
没有简单的内置方法,但您几乎可以使用 attributer 实现任何功能,如下所示:
const px2pt = 3 / 4;
function attributer(datum, index, nodes) {
var selection = d3.select(this);
if (datum.tag == "svg") {
var width = datum.attributes.width;
var height = datum.attributes.height;
w = datum.attributes.viewBox.split(" ")[2];
h = datum.attributes.viewBox.split(" ")[3];
var x = (width * px2pt - w / 2) / 2;
var y = (height * px2pt - h / 2) / 2;
selection
.attr("width", width)
.attr("height", height)
.attr("viewBox", -x + " " + -y + " " + (width * px2pt) + " " + (height * px2pt));
datum.attributes.width = width;
datum.attributes.height = height;
datum.attributes.viewBox = -x + " " + -y + " " + (width * px2pt) + " " + (height * px2pt);
}
}
d3.select("#graph").graphviz()
.width(300)
.height(300)
.fit(true)
.scale(.5)
.attributer(attributer)
.renderDot('digraph {a -> b}');
<script src="//d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="width: 300px; height: 300px; border: 1px solid black"></div>
根据 magjac 的评论,我跳过了 .fit()
、.scale()
、.width()
和 .height()
,并在属性器中完成了所有操作。这使得该解决方案甚至适用于更大的图形。
注意几点:
- 将
<svg>
的高度和宽度设置为 100%
允许我们跳过 .width()
和 .height()
并让 <svg>
填充其容器 div.
- 引入了一个
scale
变量,可以设置(0-1)来确定图形的比例
- 添加评论以帮助找到这里的人
感谢 magjac 这个很棒的库!
const scale = 0.8;
function attributer(datum, index, nodes) {
var selection = d3.select(this);
if (datum.tag == "svg") {
datum.attributes = {
...datum.attributes,
width: '100%',
height: '100%',
};
// svg is constructed by hpcc-js/wasm, which uses pt instead of px, so need to convert
const px2pt = 3 / 4;
// get graph dimensions in px. These can be grabbed from the viewBox of the svg
// that hpcc-js/wasm generates
const graphWidth = datum.attributes.viewBox.split(' ')[2] / px2pt;
const graphHeight = datum.attributes.viewBox.split(' ')[3] / px2pt;
// new viewBox width and height
const w = graphWidth / scale;
const h = graphHeight / scale;
// new viewBox origin to keep the graph centered
const x = -(w - graphWidth) / 2;
const y = -(h - graphHeight) / 2;
const viewBox = `${x * px2pt} ${y * px2pt} ${w * px2pt} ${h * px2pt}`;
selection.attr('viewBox', viewBox);
datum.attributes.viewBox = viewBox;
}
}
d3.select("#graph").graphviz()
.attributer(attributer)
.renderDot('digraph {a -> b -> c ->d -> e}');
<script src="//d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="width: 300px; height: 300px; border: 1px solid black"></div>
使用 d3-graphviz 缩放和居中图形的最佳方法是什么?我希望我可以使用 scale(0.5)
但这会使生成的图形不居中。
我可能会使用 .attributer()
并手动调整 <svg>
和 <g>
元素以获得我正在寻找的内容,但我认为可能有更好的方式?
d3.select("#graph")
.graphviz()
.width(300)
.height(300)
.fit(true)
.scale(.5)
.renderDot('digraph {a -> b}');
<script src="//d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="width: 300px; height: 300px; border: 1px solid black"></div>
没有简单的内置方法,但您几乎可以使用 attributer 实现任何功能,如下所示:
const px2pt = 3 / 4;
function attributer(datum, index, nodes) {
var selection = d3.select(this);
if (datum.tag == "svg") {
var width = datum.attributes.width;
var height = datum.attributes.height;
w = datum.attributes.viewBox.split(" ")[2];
h = datum.attributes.viewBox.split(" ")[3];
var x = (width * px2pt - w / 2) / 2;
var y = (height * px2pt - h / 2) / 2;
selection
.attr("width", width)
.attr("height", height)
.attr("viewBox", -x + " " + -y + " " + (width * px2pt) + " " + (height * px2pt));
datum.attributes.width = width;
datum.attributes.height = height;
datum.attributes.viewBox = -x + " " + -y + " " + (width * px2pt) + " " + (height * px2pt);
}
}
d3.select("#graph").graphviz()
.width(300)
.height(300)
.fit(true)
.scale(.5)
.attributer(attributer)
.renderDot('digraph {a -> b}');
<script src="//d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="width: 300px; height: 300px; border: 1px solid black"></div>
根据 magjac 的评论,我跳过了 .fit()
、.scale()
、.width()
和 .height()
,并在属性器中完成了所有操作。这使得该解决方案甚至适用于更大的图形。
注意几点:
- 将
<svg>
的高度和宽度设置为100%
允许我们跳过.width()
和.height()
并让<svg>
填充其容器 div. - 引入了一个
scale
变量,可以设置(0-1)来确定图形的比例 - 添加评论以帮助找到这里的人
感谢 magjac 这个很棒的库!
const scale = 0.8;
function attributer(datum, index, nodes) {
var selection = d3.select(this);
if (datum.tag == "svg") {
datum.attributes = {
...datum.attributes,
width: '100%',
height: '100%',
};
// svg is constructed by hpcc-js/wasm, which uses pt instead of px, so need to convert
const px2pt = 3 / 4;
// get graph dimensions in px. These can be grabbed from the viewBox of the svg
// that hpcc-js/wasm generates
const graphWidth = datum.attributes.viewBox.split(' ')[2] / px2pt;
const graphHeight = datum.attributes.viewBox.split(' ')[3] / px2pt;
// new viewBox width and height
const w = graphWidth / scale;
const h = graphHeight / scale;
// new viewBox origin to keep the graph centered
const x = -(w - graphWidth) / 2;
const y = -(h - graphHeight) / 2;
const viewBox = `${x * px2pt} ${y * px2pt} ${w * px2pt} ${h * px2pt}`;
selection.attr('viewBox', viewBox);
datum.attributes.viewBox = viewBox;
}
}
d3.select("#graph").graphviz()
.attributer(attributer)
.renderDot('digraph {a -> b -> c ->d -> e}');
<script src="//d3js.org/d3.v5.min.js"></script>
<script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
<script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>
<div id="graph" style="width: 300px; height: 300px; border: 1px solid black"></div>