how to use getElementById with getBBox to determine the svg width and height

667 Views Asked by At

I have a D3JS tree and managed to download it as an SVG file, however, I want the viewBox size to vary based on the svg box size to allow for better visualization. there are recommendation to use getElementById in conjunction with getBBox. I am not able to figure out how to pass it the correct svg content to getElementById and I am getting null for any input I provide.

As I was doubting my code, I tried it with a standard D3JS tree example to experiment with the functions usage, but still could not figure out how to use these functions.

My svg select is

 var svg = d3.select("div.svg-container-ar").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
    .call(zoom)
    .on("wheel.zoom", null) //disable zooming on mouse wheel scroll
    .on("dblclick.zoom", null)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")scale(.7,.7)");
    zoom.translate([margin.left, margin.top]).scale(.7);

and my usage of getElementById that is retuning null is

// This event is used to download SVG document
   $('#download-SVG').click(function() {
   var svgElement = document.getElementById('svg');
   // console.log(svgElement);
   let {width, height} = svgElement.getBBox();
   .
   .
   }

I would appreciate any help on this, or if there is another way to achieve variable viewBox size requirement.

1

There are 1 best solutions below

3
On

function prepareDownload(svgEl) {
  // Get bbox of the dom element.
  // In some case you may want to get the bbox from an inner <g> element
  // where the actual shapes are.
  const bBox = svgEl.node().getBBox()
  // Set the viewBox of the SVG matching the bbox
  svgEl.attr("viewBox", `${bBox.x} ${bBox.y} ${bBox.width} ${bBox.height}`)
  // Call the saving function (won't work on Stackovertflow's sandbox)
  saveSvg(svgEl.node(), 'my-svg.svg')
  // Remove the viewBox so it looks on screen the same as always
  svgEl.attr('viewBox', null)
}

function saveSvg(svgEl, name) {
  svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg")
  const svgData = svgEl.outerHTML
  console.log(svgData)
  const preface = '<?xml version="1.0" standalone="no"?>\r\n'
  const svgBlob = new Blob([preface, svgData], {type:"image/svg+xml;charset=utf-8"})
  const svgUrl = URL.createObjectURL(svgBlob)
  const downloadLink = document.createElement("a")
  downloadLink.href = svgUrl
  downloadLink.download = name
  document.body.appendChild(downloadLink)
  downloadLink.click()
  document.body.removeChild(downloadLink)
}

document.querySelector('button').addEventListener("click", function() {
  prepareDownload(d3.select("svg"))
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
<button>Download</button>
<svg>
  <circle style="fill: #69b3a2" stroke="black" cx=50 cy=50 r=40></circle>
</svg>