[javascript] d3.js 시각화 레이아웃을 반응 형으로 만드는 가장 좋은 방법은 무엇입니까?

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



답변

이 그래프를 다시 그릴 필요로하지 않는이 작업을 수행하는 또 다른 방법은, 그리고 그것을 수정 관련 뷰 박스preserveAspectRatio가 온 속성 <svg>요소를 :

<svg id="chart" width="960" height="500"
  viewBox="0 0 960 500"
  preserveAspectRatio="xMidYMid meet">
</svg>

11/24/15 업데이트 : 대부분의 최신 브라우저는 에서 SVG 요소 의 가로 세로 비율유추viewBox 할 수 있으므로 차트 크기를 최신 상태로 유지할 필요가 없습니다. 이전 브라우저를 지원해야하는 경우 창의 크기가 다음과 같이 조정될 때 요소의 크기를 조정할 수 있습니다.

var aspect = width / height,
    chart = d3.select('#chart');
d3.select(window)
  .on("resize", function() {
    var targetWidth = chart.node().getBoundingClientRect().width;
    chart.attr("width", targetWidth);
    chart.attr("height", targetWidth / aspect);
  });

그리고 svg 내용은 자동으로 조정됩니다. 여기에 약간의 수정 사항이있는 실제 작동 예를 볼 수 있습니다 . 창 또는 오른쪽 하단 창의 크기를 조정하여 반응 방식을 확인하십시오.


답변

‘반응 형 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


답변

이 문제를 해결하기 위해 작은 요점을 코딩했습니다.

일반적인 솔루션 패턴은 다음과 같습니다.

  1. 스크립트를 계산 및 그리기 기능으로 나눕니다.
  2. 그리기 기능이 동적으로 그려지고 시각화 너비 및 높이 변수로 구동되는지 확인하십시오 (이를 수행하는 가장 좋은 방법은 d3.scale api를 사용하는 것입니다).
  3. 마크 업의 참조 요소에 도면을 바인딩 / 연결합니다. (이에 jquery를 사용했기 때문에 가져 왔습니다).
  4. 이미 그려져 있으면 제거하십시오. jquery를 사용하여 참조 된 요소에서 치수를 가져옵니다.
  5. 그리기 기능을 창 크기 조정 기능에 바인딩 / 체인합니다. 타임 아웃 이후에만 다시 그리기 위해이 체인에 디 바운스 (타임 아웃)를 도입하십시오.

또한 속도를 위해 축소 된 d3.js 스크립트를 추가했습니다. 요점은 여기에 있습니다 : https://gist.github.com/2414111

jquery 참조 백 코드 :

$(reference).empty()
var width = $(reference).width();

디 바운스 코드 :

var debounce = function(fn, timeout)
{
  var timeoutID = -1;
  return function() {
     if (timeoutID > -1) {
        window.clearTimeout(timeoutID);
     }
   timeoutID = window.setTimeout(fn, timeout);
  }
};

var debounced_draw = debounce(function() {
    draw_histogram(div_name, pos_data, neg_data);
  }, 125);

 $(window).resize(debounced_draw);

즐겨!


답변

ViewBox를 사용하지 않고

다음은 다음을 사용하지 않는 솔루션의 예입니다 viewBox.

열쇠는의 범위 를 업데이트하는 것 입니다 데이터를 배치하는 데 사용되는 스케일 입니다.

먼저 원래 종횡비를 계산하십시오.

var ratio = width / height;

그런 다음 각 크기 조정에 업데이트 rangex과를 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); });
}

주에 다시 크기 조정 것을 rects당신은의 상한선 사용할 수 range의를 y명시 적으로 높이를 사용하는 대신, :

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


답변

c3.js를 통해 d3.js를 사용 하는 경우 응답 성 문제에 대한 솔루션은 매우 간단합니다.

var chart = c3.generate({bindTo:"#chart",...});
chart.resize($("#chart").width(),$("#chart").height());

생성 된 HTML은 다음과 같습니다.

<div id="chart">
    <svg>...</svg>
</div>


답변

Shawn Allen의 답변은 훌륭했습니다. 그러나 매번이 작업을 수행하지 않을 수도 있습니다. 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에 빌드합니다 .


답변

plottable.js 와 같은 d3 래퍼를 사용하는 경우 가장 쉬운 해결책은 이벤트 리스너를 추가 한 다음 다시 그리기 함수 ( plottable.js에서) 를 호출하는 것 입니다. plottable.js의 경우 이것은 훌륭하게 작동합니다 (이 접근법은 잘 문서화되어 있지 않습니다).redraw

    window.addEventListener("resize", function() {
      table.redraw();
    });