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
답변
이 문제를 해결하기 위해 작은 요점을 코딩했습니다.
일반적인 솔루션 패턴은 다음과 같습니다.
- 스크립트를 계산 및 그리기 기능으로 나눕니다.
- 그리기 기능이 동적으로 그려지고 시각화 너비 및 높이 변수로 구동되는지 확인하십시오 (이를 수행하는 가장 좋은 방법은 d3.scale api를 사용하는 것입니다).
- 마크 업의 참조 요소에 도면을 바인딩 / 연결합니다. (이에 jquery를 사용했기 때문에 가져 왔습니다).
- 이미 그려져 있으면 제거하십시오. jquery를 사용하여 참조 된 요소에서 치수를 가져옵니다.
- 그리기 기능을 창 크기 조정 기능에 바인딩 / 체인합니다. 타임 아웃 이후에만 다시 그리기 위해이 체인에 디 바운스 (타임 아웃)를 도입하십시오.
또한 속도를 위해 축소 된 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;
그런 다음 각 크기 조정에 업데이트 range
의 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); });
}
주에 다시 크기 조정 것을 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();
});