我正在尝试在d3内的窗口大小调整上重绘SVG图表,但没有使用viewBox
和preserveAspectRatio
参数(我不喜欢他们如何处理文本)。
在添加单个元素(不基于支持的数据)时,我也试图通过Bostock的suggestion坚持使用d3的数据绑定设计。
我有一些归结为此(jsFiddle)。但是SVG元素的宽度/高度永远不会更新。
<div class="chart-container">
<button class="user-option">Some User Options</button>
<div class="svg-container"></div>
</div>
$(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
});
}
答案 0 :(得分:3)
这里的根本问题是你的svg变量没有被分配<svg>
元素选择,它被分配了链式方法调用的最终结果,第一次是{{{ 1}}元素,之后是空的,因为没有&#39;输入&#39;选择。
首先要做的是改为
<g>
首次执行时,更新选择将为空,输入选择将包含单个元素。然后将其绑定到新的var svg = container.select(".svg-container").selectAll('svg').data([0]);
// now you have a reference to the svg selection
元素:
<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
答案 1 :(得分:1)
@Pablo Navarro的答案是关闭唯一的问题是重绘上的svg不会是你的svg元素而是一个数组,使用相同的技术分离两个执行但是专门选择你的svg再来改变宽度和高度
var svg = container.select(".svg-container").selectAll('svg')
.data([0]) // Single data element to create SVG if it doesn't exist
.enter().append("svg")
.append("g")
.attr("class", "canvas")
// jsFiddle doesn't translate correctly, maybe because of frames???
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
然后
container.select(".svg-container").select('svg').attr("width", drawWidth).attr("height", drawHeight)
答案 2 :(得分:1)
谢谢,我能够从你的所有答案中找到正确的解决方案!但是,没有一个答案能够在调整大小时更新SVG AND 将svg
变量保留为g
元素(以坚持margin convention)。我最终做了
// Create SVG element (if it doesn't exist)
var svg = container.select(".svg-container").selectAll('svg').data([null]);
svg.enter().append("svg");
svg.attr({width: drawWidth, height: drawHeight}); // apply to enter + update selections
// Create g element (if it doesn't exist) and remap the svg variable
svg = svg.selectAll(".canvas").data([null]);
svg.enter().append("g") // apply to enter selection only
.attr("class", "canvas")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
答案 3 :(得分:0)
您只在输入时设置svg元素的宽度和高度,如果该元素已存在,则不会更新。尝试在创建元素(和子组)后更新元素:
var svg = container.select(".svg-container").selectAll('svg')
.data([0]) // Single data element to create SVG if it doesn't exist
.enter().append("svg")
.append("g")
.attr("class", "canvas")
// jsFiddle doesn't translate correctly, maybe because of frames???
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
svg.attr("width", drawWidth).attr("height", drawHeight)
此致