CQM
CQM

Reputation: 44278

How to create responsive svg using d3.js

I need my SVG in a webpage to dynamically resize based on window size, or to have multiple hardcoded widths and heights.

I am using the D3 library.

My problem is that it isn't just the SVG tag that needs a different canvas size, it is the children elements such as a rect tag and g tag that also need to resize or be completely re-rendered

How would this be done?

I realize I could listen to window resizing with

d3.select(window).on('resize', resize);

with my resize function doing all the logic, but exactly how and what width/heights to choose (or calculate) is beyond me

<div class="svg-container">
<svg width="960" height="500" preserveAspectRatio="xMidYMid" class="svg-content">
   <defs>
     <clipPath id="clip-upper">
      <rect id="rect-clip-upper" width="960" height="305" x="-480" y="-305">      </rect>
</clipPath>
<clipPath id="clip-lower">
  <rect id="rect-clip-lower" width="960" height="195" x="-480" y="0"></rect>
</clipPath>
</defs>
   <g clip-path="url(#clip-upper)" transform="translate(480,305)"></g>
   <g clip-path="url(#clip-lower)" transform="translate(480,305)"></g>
 </svg>

Upvotes: 2

Views: 951

Answers (3)

Himesh Aadeshara
Himesh Aadeshara

Reputation: 2131

Hi SVG it self suggest "Salable vector graphics" so it is responsive by nature so for that you just need to use "viewBox" attribute of <svg> element. with your perspective use.

Upvotes: 1

quw
quw

Reputation: 2854

Instead of hardcoding a width, make it dependent upon the width of the parent of the svg. E.g.

width = svgParent[0][0].clientWidth - margin.left - margin.right;
height = svgParent[0][0].clientHeight - margin.top - margin.bottom;

Make sure that all your widths, heights, and positions are either calculated from data (in which case d3 will handle it) or relate to width/height in some way. Then, in your resize handler, just call child.attr("width", newWidth), child.attr("x", newX), etc. on all elements you want to resize.

If you're using axes, set the range to your new width value and call the axis function again (i.e. svg.select(".x.axis").call(xAxis)). If you are using zoom or other similar features, you'll have to call them again.

Upvotes: 1

Robert Longson
Robert Longson

Reputation: 124249

If you add a viewBox to the svg element e.g. viewBox="0 0 960 500" you won't need to resize any children.

Upvotes: 2

Related Questions