51

I'm trying to alter an SVG elements viewbox in JavaScript. Basically, I'm drawing a binary search tree, and when it gets too wide, I want to alter the viewbox to zoom out so that the tree fits in the window. I'm currently using:

if(SVGWidth>=1000){
  var a = document.getElementById('svgArea');
  a.setAttribute("viewbox","0 0 " + SVGWidth + " 300");
}

The HTML is:

<svg id="svgArea" xmlns="w3.org/2000/svg"; xmlns:xlink="w3.org/1999/xlink"; width="1000" height="300" viewBox="0 0 1000 300">

I've also tried using setAttributeNS('null',...) but that didn't seem to work either. One strange thing I've noticed is that when I alert(a) it gives [object SVGSVGElement] which seems strange. Any help is appreciated.

Rene Pot
  • 24,681
  • 7
  • 68
  • 92
Andrew Clear
  • 7,910
  • 5
  • 27
  • 35
  • may I know why you don't want to use libraries? – Rene Pot Apr 10 '12 at 08:01
  • I should have added, SVGWidth is probably a bad variable name, should just be treeWidth. Also, the html for the SVG is: – Andrew Clear Apr 10 '12 at 08:01
  • 6
    I'm not using libraries because I'm focusing on learning JavaScript. My next project I'll add in libraries, but I thought it would be best to start with native JavaScript. – Andrew Clear Apr 10 '12 at 08:02
  • 6
    @aclear16 : Probably using a library to achieve this would be frustrating, since it should work and since it would only limit the OP's general understanding of DOM manipulation (and thus they would be at the mercy of the library). While we shouldn't be expected to understand things down to the assembly level, it's always helpful to understand how something you are already working within actually works rather than rely on libraries. – Anthony Apr 10 '12 at 08:09

4 Answers4

99

It would be good to see the context of the svg, but the following worked for me with a pure SVG document:

shape = document.getElementsByTagName("svg")[0];
shape.setAttribute("viewBox", "-250 -250 500 750"); 

Maybe it's because viewBox is case-sensitive?

Anthony
  • 36,459
  • 25
  • 97
  • 163
  • 5
    Look at it this way, if it hadn't been that easy, it would have been harder. And I never tried messing with the actual svg element attributes until now, so we both figured something out. – Anthony Apr 10 '12 at 08:11
  • 7
    I made the same mistake. – Joseph Jaquinta Feb 08 '13 at 22:12
  • 11
    For dynamically created SVGs, the SVG element would need to be created using `createElementNS` or else setting the attribute `viewBox` would not work. Reference: https://stackoverflow.com/questions/28734628/how-can-i-set-an-attribute-with-case-sensitive-name-in-a-javascript-generated-el/28734954#28734954 – Benjamin Intal Nov 20 '17 at 05:11
  • 1
    More precisely, the DOM SVG object has only `viewBox` attribute. is has no `viewbox` attribute, even though you write `viewbox` in the HTML – Eric Dec 01 '17 at 09:37
  • 1
    I believe that this should be `setAttributeNs(null, "viewBox", ...)` and that `setAttribute` *happens* to work, but may not work in the future. Please correct me if I am mistaken, since I am not 100% sure on this. – Charles L. Jul 15 '18 at 22:46
  • @CharlesL. - I think you are correct. I said as much myself on another answer: https://stackoverflow.com/questions/10546135/appending-path-child-within-svg-using-javascript/10546700#10546700 – Anthony Jul 16 '18 at 21:24
  • 1
    I can confirm that `viewBox` *is* case sensitive. – Code4R7 Jul 19 '21 at 08:14
12

You have an error in your code: "viewbox" is different than "viewBox"...B is in uppercase. Change the code to:

a.setAttribute("viewBox","0 0 " + SVGWidth + " 300");
altocumulus
  • 21,179
  • 13
  • 61
  • 84
LUISAO
  • 121
  • 1
  • 5
  • Well, I think the way the answer now is does answer the question. The 'b' was the reason it didn't work. However, user3434597 should have read @Anthony's older answer first. Maybe he'll remove this one. – akauppi Feb 12 '15 at 22:08
0

I had a very similar use case, where resizing SVG was crucial for responsive design.

const windowWidth = window.innerWidth ||
  document.documentElement.clientWidth ||
  document.body.clientWidth;

const windowHeight = window.innerHeight ||
  document.documentElement.clientHeight ||
  document.body.clientHeight;

// used getElementById for specific SVG
const shape = document.getElementById("background-svg");

function onWindowResize(){
console.log(windowWidth, windowHeight);

if (windowWidth < 600 || windowHeight < 900) {
  shape.setAttribute("viewBox", "0 0 400 800");
}

// Added an Event Listener
window.addEventListener("resize", onWindowResize);

This method worked well enough for me, I hope there's room for improvement, would be glad to find alternative solutions. Happy coding!

0

Additionally, if you want to set the view box dimension dynamically then use ES6 template literals instead of string concatenation.

shape = document.getElementsByTagName("svg")[0];
const view = `${xValue} ${yValue} ${width} ${height}`; // template literals
shape.setAttribute("viewBox", view); 
SridharKritha
  • 8,481
  • 2
  • 52
  • 43