使用JavaScript修改SVG属性没有效果

13
我试图使用JavaScript修改一个SVG标签,使其可调整大小,但我的更改没有效果。我需要这样做的原因是这个标签是由一个我无法修改的库渲染的,因此似乎唯一的选择是使用JavaScript修改SVG。
我知道该脚本生成的标签是正确的,因为我可以将该标签复制到新的HTML文档中并且它能正常工作(我已将其包含在示例代码中),所以似乎我需要一种方法来强制SVG识别其已被更改(或另一种方式来修改SVG)。
这里有一个显示我的问题的HTML页面:
<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>
2个回答

25

SVG是区分大小写的,因此

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

应该被书写

svg.setAttribute('viewBox', '0 0 ' + w + ' ' + h);
svg.setAttribute('preserveAspectRatio', 'xMinYMin meet')

<svg>元素上的宽度和高度是属性而不是样式(与html不同),因此您应该使用setAttribute('width', '100%')而不是.css('width', '100%')


22
给其他谷歌员工的提示:请注意在find('svg')之后添加[0]以获取jQuery元素中的DOM元素。这一点很重要,可以使setAttribute()方法可用。不能使用jQuery的attr()方法,因为SVG DOM与HTML DOM不同(参见http://keith-wood.name/svg.html#dom)。 - Offirmo
只有在不使用JQuery SVG(可能)的情况下才是真实的。链接中明确说明了这一点。SVG DOM与jQuery设计的HTML DOM不同。因此,jQuery用于处理类的函数无法在SVG节点上工作。为了解决这个问题,您可以使用jQuery SVG DOM扩展。将扩展添加到页面的头部即可。我不明白为什么这不能用于任何SVG问题,但它可能太过嵌入JquerySVG,但是谁知道一些编辑会做什么 :) - XaolingBao

7

jQuery将属性名称转换为小写;例如,它将设置viewBox属性为viewbox。不幸的是,SVG(一种XML方言)元素属性名称区分大小写。

如果您想始终使用jQuery,可以使用$.attrHooks来处理区分大小写的属性:

['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'
  })
});

请注意,el.attr('viewBox',null)将失败;您的挂钩设置程序不会被调用。相反,您应该使用el.removeAttr('viewBox')el.attr('viewBox',false)
对于像stroke这样的其他属性,我会将它们放在样式表中。
svg {
  background-color: white;
}
circle {
  fill: red;
  stroke: black;
  stroke-width: 1px;
}

如果你需要添加/切换类来改变特定元素的样式,你需要使用jQuery 1.12+或jquery 2.2+。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接