在d3.js中调整窗口大小时调整svg的大小
我用d3.js绘制散点图 在这个问题的帮助下:
获取屏幕的大小,当前网页和浏览器窗口
我正在使用这个答案:
var w = window, d = document, e = d.documentElement, g = d.getElementsByTagName('body')[0], x = w.innerWidth || e.clientWidth || g.clientWidth, y = w.innerHeight|| e.clientHeight|| g.clientHeight;
所以我可以像这样把我的情节适合用户的窗口:
var svg = d3.select("body").append("svg") .attr("width", x) .attr("height", y) .append("g");
现在,我希望在用户调整窗口大小时重新resize。
PS:我没有在我的代码中使用jQuery。
寻找“响应SVG”,使SVG响应非常简单,而且不必再担心大小。
我是这样做的:
d3.select("div#chartId") .append("div") .classed("svg-container", true) //container class to make it responsive .append("svg") //responsive SVG needs these 2 attributes and no width and height attr .attr("preserveAspectRatio", "xMinYMin meet") .attr("viewBox", "0 0 600 400") //class to make it responsive .classed("svg-content-responsive", true);
CSS代码:
.svg-container { display: inline-block; position: relative; width: 100%; padding-bottom: 100%; /* aspect ratio */ vertical-align: top; overflow: hidden; } .svg-content-responsive { display: inline-block; position: absolute; top: 10px; left: 0; }
更多信息/教程:
http://thenewcode.com/744/Make-SVG-Responsive
http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php
使用window.onresize :
function updateWindow(){ x = w.innerWidth || e.clientWidth || g.clientWidth; y = w.innerHeight|| e.clientHeight|| g.clientHeight; svg.attr("width", x).attr("height", y); } d3.select(window).on('resize.updatesvg', updateWindow);
更新只是使用从@cminatti新的方式
旧的回答为历史的目的
国际海事组织最好使用select()和on(),因为这样你可以有多个resize事件处理程序…只是不要太疯狂
d3.select(window).on('resize', resize); function resize() { // update width width = parseInt(d3.select('#chart').style('width'), 10); width = width - margin.left - margin.right; // resize the chart x.range([0, width]); d3.select(chart.node().parentNode) .style('height', (y.rangeExtent()[1] + margin.top + margin.bottom) + 'px') .style('width', (width + margin.left + margin.right) + 'px'); chart.selectAll('rect.background') .attr('width', width); chart.selectAll('rect.percent') .attr('width', function(d) { return x(d.percent); }); // update median ticks var median = d3.median(chart.selectAll('.bar').data(), function(d) { return d.percent; }); chart.selectAll('line.median') .attr('x1', x(median)) .attr('x2', x(median)); // update axes chart.select('.x.axis.top').call(xAxis.orient('top')); chart.select('.x.axis.bottom').call(xAxis.orient('bottom')); }
http://eyeseast.github.io/visible-data/2013/08/28/responsive-charts-with-d3/
如果resize的代码几乎和用于构buildgraphics的代码几乎一样长,那就太难看了。 因此,不要调整现有图表的每个元素,为什么不简单地重新加载呢? 以下是我如何工作:
function data_display(data){ e = document.getElementById('data-div'); var w = e.clientWidth; // remove old svg if any -- otherwise resizing adds a second one d3.select('svg').remove(); // create canvas var svg = d3.select('#data-div').append('svg') .attr('height', 100) .attr('width', w); // now add lots of beautiful elements to your graph // ... } data_display(my_data); // call on page load window.addEventListener('resize', function(event){ data_display(my_data); // just call it again... }
关键的一行是d3.select('svg').remove();
。 否则,每个resize将在前一个下面添加另一个SVG元素。
在强制布局中,简单地设置“高度”和“宽度”属性将无法将绘图重新居中/移动到svg容器中。 然而,这里有一个非常简单的解决scheme,适用于Force Layouts。 综上所述:
使用相同的(任何)事件你喜欢。
window.on('resize', resize);
然后假设你有svg&强制variables:
var svg = /* D3 Code */; var force = /* D3 Code */; function resize(e){ // get width/height with container selector (body also works) // or use other method of calculating desired values var width = $('#myselector').width(); var height = $('#myselector').height(); // set attrs and 'resume' force svg.attr('width', width); svg.attr('height', height); force.size([width, height]).resume(); }
通过这种方式,您不会完全重新渲染graphics,我们设置属性并根据需要重新计算d3。 这至less在你使用重力点的时候起作用。 我不确定这是否是此解决scheme的先决条件。 任何人都可以确认或否认?
干杯,克