我正在尝试在 d3 中重新绘制窗口调整大小的 SVG 图表,但没有使用 viewBox
和 preserveAspectRatio
参数(我不喜欢他们处理文本的方式).
我还试图通过 Bostock 的 suggestion 坚持使用 d3 的数据绑定(bind)设计。附加单个元素时(不基于支持的数据)。
我有一些事情可以归结为这个 ( jsFiddle )。然而,SVG 元素的宽度/高度永远不会更新。
HTML
<div class="chart-container">
<button class="user-option">Some User Options</button>
<div class="svg-container"></div>
</div>
Javascript
$(window).on("resize", function () {
draw();
});
function draw() {
var container = d3.select('.chart-container');
var drawWidth = Math.round(0.80 * container.node().clientWidth);
var drawHeight = Math.round(drawWidth * (3 / 4)); // Fixing a 4/3 aspect ratio
/*
* Use an inner g element as the SVG canvas in order to set and forget margins.
* See http://bl.ocks.org/mbostock/3019563
*/
var margin = {
top: 10,
right: 30,
bottom: 50,
left: 40
};
var width = drawWidth - margin.left - margin.right;
var height = drawHeight - margin.top - margin.bottom;
var svg = container.select(".svg-container").selectAll('svg')
.data([0]) // Single data element to create SVG if it doesn't exist
.enter().append("svg")
.attr("width", drawWidth)
.attr("height", drawHeight)
.append("g")
.attr("class", "canvas")
// jsFiddle doesn't translate correctly, maybe because of frames???
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
console.debug(svg.node()); // null on resize???
// Add some random SVG element
svg.selectAll('rect')
.data([0]) // Single data element to create SVG if it doesn't exist
.enter().append('rect')
.attr({
x: 0,
y: 0,
width: drawWidth - margin.right - margin.left,
height: drawHeight - margin.bottom - margin.top
});
}
最佳答案
这里的根本问题是您的 svg 变量没有被分配 <svg>
元素选择,它被分配链式方法调用的最终结果,第一次是 <g>
元素,之后是空的,因为没有“输入”选择。
所以首先要做的是更改为
var svg = container.select(".svg-container").selectAll('svg').data([0]);
// now you have a reference to the svg selection
第一次执行时,更新选择将为空,输入选择将只有一个元素。然后将其绑定(bind)到一个新的 <svg>
元素:
svg.enter()
.append("svg")
.append("g")
// note that from this point you're setting attributes on the <g>, not the <svg>
.attr("class", "canvas")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
此附加操作还将元素添加到存储在 svg
中的更新选择中.
调整大小时,输入选择将为空,但更新选择在svg
将已经包含现有的 <svg>
元素。所以无论哪种方式,此时您都可以在 svg
上设置属性选择 - 它适用于这两种情况。
svg.attr("width", drawWidth)
.attr("height", drawHeight);
更新 fiddle http://jsfiddle.net/3dgn5pz8/5/
关于javascript - 在调整大小时重绘 SVG,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25555257/