programing

d3.js에서 창 크기를 조정할 때 svg 크기 조정

projobs 2022. 12. 10. 14:04
반응형

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");

이제 사용자가 창의 크기를 조정할 때 플롯의 크기를 조정해 주었으면 합니다.

PS: 제 코드에 jQuery를 사용하지 않습니다.

'응답형 SVG'를 찾으십시오. SVG를 응답형 SVG로 만드는 것은 매우 간단하며, 더 이상 크기에 대해 걱정할 필요가 없습니다.

방법은 다음과 같습니다.

d3.select("div#chartId")
   .append("div")
   // Container class to make it responsive.
   .classed("svg-container", true) 
   .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)
   // Fill with a rectangle for visualization.
   .append("rect")
   .classed("rect", true)
   .attr("width", 600)
   .attr("height", 400);
.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;
}

svg .rect {
  fill: gold;
  stroke: steelblue;
  stroke-width: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div id="chartId"></div>

주의: SVG 이미지의 모든 것은 창 너비에 따라 확대됩니다.여기에는 스트로크 폭과 글꼴 크기(CSS로 설정된 크기도 포함)가 포함됩니다.이것이 바람직하지 않은 경우는, 이하와 같은 대체 솔루션이 있습니다.

상세정보/자습서:

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);

http://jsfiddle.net/Zb85u/1/

UPDATE는 @cminatti에서 새로운 방법을 사용합니다.


역사적 목적을 위한 오래된 대답

IMO는 select()와 on()을 사용하는 것이 좋습니다.이렇게 하면 여러 개의 이벤트핸들러를 사이즈 변경할 수 있기 때문입니다.너무 흥분하지 마

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/

크기 조정 코드가 그래프를 만드는 코드와 거의 같다면 좀 못생겼죠.따라서 기존 차트의 모든 요소의 크기를 조정하는 대신 단순히 다시 로드하는 것이 어떻습니까?저는 다음과 같이 작업을 진행했습니다.

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();그렇지 않으면 크기를 조정할 때마다 이전 SVG 요소 아래에 다른 SVG 요소가 추가됩니다.

레이아웃에서는 단순히 '높이' 및 '너비' 속성을 설정하여 플롯을 svg 컨테이너로 다시 중심화/이동할 수 없습니다.그러나 Force Layouts에 적합한 매우 간단한 답이 여기에 있습니다.요약:

원하는 대로 같은 것을 사용하세요.

window.on('resize', resize);

다음으로 svg 및 force 변수가 있다고 가정합니다.

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();
}

이 방법으로 그래프를 완전히 다시 렌더링하지 않고 속성을 설정하고 필요에 따라 d3를 다시 계산합니다.이것은 적어도 중력점을 사용할 때는 효과가 있습니다.그것이 이 해결책의 전제 조건인지 잘 모르겠습니다.확인 또는 부인할 수 있는 사람?

건배, g

커스텀 로직을 바인드하여 이벤트의 크기를 조정하고 싶다면, 현재는 SVGElement의 경계 상자에 ResizeObserver 브라우저 API를 사용할 수 있습니다.
이것은 또한 근처의 요소 크기 변경으로 인해 컨테이너 크기가 조정되는 경우를 처리합니다.
광범위한 브라우저 지원을 위한 폴리필이 있습니다.

UI 컴포넌트에서는 다음과 같이 동작합니다.

function redrawGraph(container, { width, height }) {
  d3
    .select(container)
    .select('svg')
    .attr('height', height)
    .attr('width', width)
    .select('rect')
    .attr('height', height)
    .attr('width', width);
}

// Setup observer in constructor
const resizeObserver = new ResizeObserver((entries, observer) => {
  for (const entry of entries) {
    // on resize logic specific to this component
    redrawGraph(entry.target, entry.contentRect);
  }
})

// Observe the container
const container = document.querySelector('.graph-container');
resizeObserver.observe(container)
.graph-container {
  height: 75vh;
  width: 75vw;
}

.graph-container svg rect {
  fill: gold;
  stroke: steelblue;
  stroke-width: 3px;
}
<script src="https://unpkg.com/resize-observer-polyfill@1.5.1/dist/ResizeObserver.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<figure class="graph-container">
  <svg width="100" height="100">
    <rect x="0" y="0" width="100" height="100" />
  </svg>
</figure>

// unobserve in component destroy method
this.resizeObserver.disconnect()

directed 하는 사용자는 D3 v4/v5를 합니다.size메서드는 더 이상 존재하지 않습니다.다음과 같은 것이 나에게 효과가 있었다(이 github 문제에 근거한다).

simulation
    .force("center", d3.forceCenter(width / 2, height / 2))
    .force("x", d3.forceX(width / 2))
    .force("y", d3.forceY(height / 2))
    .alpha(0.1).restart();

언급URL : https://stackoverflow.com/questions/16265123/resize-svg-when-window-is-resized-in-d3-js

반응형