假设我有一个直方图脚本,构建960 500 svg图形。我如何使这个响应,以便调整图形的宽度和高度是动态的?

<script> 

var n = 10000, // number of trials
    m = 10,    // number of random variables
    data = [];

// Generate an Irwin-Hall distribution.
for (var i = 0; i < n; i++) {
  for (var s = 0, j = 0; j < m; j++) {
    s += Math.random();
  }
  data.push(s);
}

var histogram = d3.layout.histogram()
    (data);

var width = 960,
    height = 500;

var x = d3.scale.ordinal()
    .domain(histogram.map(function(d) { return d.x; }))
    .rangeRoundBands([0, width]);

var y = d3.scale.linear()
    .domain([0, d3.max(histogram.map(function(d) { return d.y; }))])
    .range([0, height]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.selectAll("rect")
    .data(histogram)
  .enter().append("rect")
    .attr("width", x.rangeBand())
    .attr("x", function(d) { return x(d.x); })
    .attr("y", function(d) { return height - y(d.y); })
    .attr("height", function(d) { return y(d.y); });

svg.append("line")
    .attr("x1", 0)
    .attr("x2", width)
    .attr("y1", height)
    .attr("y2", height);

</script> 

完整的直方图示例要点如下: https://gist.github.com/993912


当前回答

寻找“响应式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://demosthenes.info/blog/744/Make-SVG-Responsive

http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php

其他回答

寻找“响应式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://demosthenes.info/blog/744/Make-SVG-Responsive

http://soqr.fr/testsvg/embed-svg-liquid-layout-responsive-web-design.php

肖恩·阿伦的回答很棒。但你可能不想每次都这么做。如果你把它放在vida上。Io,您可以自动响应SVG可视化。

你可以用这个简单的嵌入代码获得响应式iframe:

<div id="vida-embed">
<iframe src="http://embed.vida.io/documents/9Pst6wmB83BgRZXgx" width="auto" height="525" seamless frameBorder="0" scrolling="no"></iframe>
</div>

#vida-embed iframe {
  position: absolute;
  top:0;
  left: 0;
  width: 100%;
  height: 100%;
}

http://jsfiddle.net/dnprock/npxp3v9d/1/

披露:我在vida.io上构建了这个功能。

这里有很多复杂的答案。

基本上你所需要做的就是抛弃width和height属性,转而使用viewBox属性:

width = 500;
height = 500;

const svg = d3
  .select("#chart")
  .append("svg")
  .attr("viewBox", `0 0 ${width} ${height}`)

如果你有边距,你可以把它们加到宽/高中,然后在后面加上g,像平常一样变换它。

我会避免像瘟疫一样调整大小/标记的解决方案,因为它们效率很低,并且会在你的应用程序中引起问题(例如,工具提示重新计算它应该出现在窗口调整大小上的位置,然后一会儿你的图表也会调整大小,页面重新布局,现在你的工具提示又错了)。

你可以在一些旧的浏览器中模拟这种行为,比如IE11,使用<canvas>元素来维护它的方面。

给定960x540,这是16:9的一个方面

<div style="position: relative">
  <canvas width="16" height="9" style="width: 100%"></canvas>
  <svg viewBox="0 0 960 540" preserveAspectRatio="xMidYMid meet" style="position: absolute; top: 0; right: 0; bottom: 0; left: 0; -webkit-tap-highlight-color: transparent;">
  </svg>
</div>

不使用ViewBox

下面是一个不依赖viewBox的解决方案的例子:

关键在于更新用于放置数据的尺度范围。

首先,计算你的原始纵横比:

var ratio = width / height;

然后,在每次调整大小时,更新x和y的范围:

function resize() {
  x.rangeRoundBands([0, window.innerWidth]);
  y.range([0, window.innerWidth / ratio]);
  svg.attr("height", window.innerHeight);
}

请注意,高度是基于宽度和长宽比,所以你的原始比例是保持不变的。

最后,“重绘”图表——更新任何依赖于x或y刻度的属性:

function redraw() {
    rects.attr("width", x.rangeBand())
      .attr("x", function(d) { return x(d.x); })
      .attr("y", function(d) { return y.range()[1] - y(d.y); })
      .attr("height", function(d) { return y(d.y); });
}

注意,在调整矩形的大小时,你可以使用y范围的上界,而不是显式地使用height:

.attr("y", function(d) { return y.range()[1] - y(d.y); })

var n = 10000, // number of trials m = 10, // number of random variables data = []; // Generate an Irwin-Hall distribution. for (var i = 0; i < n; i++) { for (var s = 0, j = 0; j < m; j++) { s += Math.random(); } data.push(s); } var histogram = d3.layout.histogram() (data); var width = 960, height = 500; var ratio = width / height; var x = d3.scale.ordinal() .domain(histogram.map(function(d) { return d.x; })) var y = d3.scale.linear() .domain([0, d3.max(histogram, function(d) { return d.y; })]) var svg = d3.select("body").append("svg") .attr("width", "100%") .attr("height", height); var rects = svg.selectAll("rect").data(histogram); rects.enter().append("rect"); function redraw() { rects.attr("width", x.rangeBand()) .attr("x", function(d) { return x(d.x); }) // .attr("y", function(d) { return height - y(d.y); }) .attr("y", function(d) { return y.range()[1] - y(d.y); }) .attr("height", function(d) { return y(d.y); }); } function resize() { x.rangeRoundBands([0, window.innerWidth]); y.range([0, window.innerWidth / ratio]); svg.attr("height", window.innerHeight); } d3.select(window).on('resize', function() { resize(); redraw(); }) resize(); redraw(); <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>