Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Modifying svg attributes with javascript has no effect

I'm trying to modify an svg tag with javascript to make it resizable, but my changes have no effect. The reason that I need to do this is that this tag is rendered by a library that I can't modify, and thus it seems like my only choice is to modify the svg with javascript.

I know that the tag that this script produces is correct since I am able to copy the tag to a new html document and it will work (I have included it in the sample code), so it seems like I need some way to force the svg to recognize that it has been changed (or another way to modify the svg).

Here's a HTML page that shows my problem:

<html>
    <head>
        <script src="http://code.jquery.com/jquery.min.js"></script>
        <script type="text/javascript">
        $(document).ready(function () {
            var svg = $('#testsvg').find('svg')[0];

            var w = svg.getAttribute('width').replace('px', '');
            var h = svg.getAttribute('height').replace('px', '');

            svg.removeAttribute('width');
            svg.removeAttribute('height');

            svg.setAttribute('viewbox', '0 0 ' + w + ' ' + h);
            svg.setAttribute('preserveaspectratio', 'xminymin meet')

            $(svg)
                .css('width', '100%')
                .css('height', '100%')
                .css('background-color', 'white');
        });
        </script>
    </head>
    <body style="background-color: #333;">
        <div style="width: 80%; height: 40%;">
            <svg id="resultsvg" xmlns="http://www.w3.org/2000/svg" version="1.1" style="width: 100%; height: 100%; background-color: white; " viewbox="0 0 100 100" preserveaspectratio="xminymin meet">
                <circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red"></circle>
            </svg>
         </div>
        <div id="testsvg" style="width: 80%; height: 40%;">
            <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100px" height="100px">
                <circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
            </svg>
        </div>
     </body>
</html>
like image 547
Nocklas Avatar asked Jun 11 '12 00:06

Nocklas


People also ask

How to change SVG attributes JavaScript?

Changing Attribute Values Once you have obtained a reference to the SVG element you can change its attributes using the setAttribute() function. Here is an example: var svgElement = document. getElementById("rect1"); svgElement.

Can SVG integrate with JavaScript?

Since SVG images can be inlined in HTML, we can manipulate them with JavaScript. This means that we can animate parts of an image from code, make it interactive, or turn things around and generate graphics from data.

What is SVG attributes?

SVG presentation attributes are CSS properties that can be used as attributes on SVG elements. alignment-baseline. baseline-shift. clip. clip-rule.


1 Answers

jQuery convert attribute name to lower case; e.g., instead of setting a viewBox attribute, it will set viewbox. Unfortunately, SVG (a XML dialect) element attribute names are case sensitive.

If you wanted to use jQuery consistently, you could use $.attrHooks to handle the case sensitive attributes:

['preserveAspectRatio', 'viewBox'].forEach(function(k) {
  // jQuery converts the attribute name to lowercase before
  // looking for the hook. 
  $.attrHooks[k.toLowerCase()] = {
    set: function(el, value) {
      if (value) {
        el.setAttribute(k, value);
      } else {
        el.removeAttribute(k, value);
      }
      return true;
    },
    get: function(el) {
      return el.getAttribute(k);
    },
  };
});

$(document).ready(function() {
  var svg = $('#testsvg');
  var w = svg.attr('width').replace('px', '');
  var h = svg.attr('height').replace('px', '');

  svg.attr({
    width: '100%',
    height: '100%',
    viewBox: [0, 0, w, h].join(' '),
    preserveAspectRatio: 'xMidYMid meet'
  })
});

Note that el.attr('viewBox', null) would failed; your hook setter won't be called. Instead you should use el.removeAttr('viewBox') or el.attr('viewBox', false).

For other attribute like stroke, I would put them in a stylesheet.

svg {
  background-color: white;
}
circle {
  fill: red;
  stroke: black;
  stroke-width: 1px;
}

If you need to add/toggle class to change the style of a specific elements, you need to use jQuery 1.12+ or jquery 2.2+.

like image 181
Dinoboff Avatar answered Oct 17 '22 18:10

Dinoboff