【问题标题】:How do I create a style sheet for an SVG element?如何为 SVG 元素创建样式表?
【发布时间】:2014-07-23 20:18:59
【问题描述】:

我尝试向 SVG 元素添加样式表,如下所示:

var theSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var theStyle = document.createElementNS("http://www.w3.org/2000/svg", "style");
theSvg.appendChild(theStyle);
console.log("theStyle.sheet=", theStyle.sheet); // undefined, try adding svg to DOM
document.body.appendChild(theSvg);
console.log("theStyle.sheet=", theStyle.sheet); // still undefined

我应该怎么做才能到达theStyle 中的工作表节点?

这里有一个小提琴:http://jsfiddle.net/XaV7D/2/

【问题讨论】:

标签: javascript dom svg stylesheet


【解决方案1】:

正如@RobertLongson 在 cmets 中指出的那样,问题在于SVG specs define a svg:style element interface,但它没有实现the CSS OM interfaces associated with a stylesheet's owner element

这里有一些变通方法(在等待 SVG 2 规范实施最新的 CSS OM 规范时):

  1. 使用 (X)HTML 样式元素。如果您的 SVG 代码内嵌在 (X)HTML 文档中,则 HTML <style> 元素可用于设置 SVG 样式。只需确保在默认命名空间中创建样式元素或在 XHTML 命名空间中显式创建样式元素,以便获得HTMLStyleElement 的实例,而不是SVGStyleElement

    将新创建的 HTMLStyleElement 添加到文档的头部,CSS 样式表对象将为您创建:

    var hs = document.createElement("style");
    hs.type = "text/css";
    document.head.insertBefore(hs, null);
    hs.sheet.insertRule("circle{fill:red;}", 0); 
    

    This answer goes into more detail about dynamically creating stylesheets in HTML, including a working example.

  2. (理论上)使用xml-stylesheet processing instruction。如果您的 SVG 代码位于独立的 SVG 文件中,那么您可以使用 XML 处理指令来链接外部样式表。处理指令节点提供对样式表对象的访问。

    然而,与可以为空的<style> 元素不同,处理指令节点必须 链接到文件,否则浏览器将永远不会初始化样式表对象。我试图通过将外部文件定义为正确 MIME 类型的空数据 URI 来解决这个问题。 当从控制台运行时,它通常(但不一致)在 FF/Chrome 中运行,但不是从嵌入式脚本运行。 在 Chrome 中,sheet 属性始终为空,与 Chrome 处理交叉的方式相同- 域样式表; Firefox 给出了一个明确的安全错误。我认为它在 IE 中根本不起作用,它不喜欢非图像数据 URI 文件。

    var xs = document.createProcessingInstruction(
        "xml-stylesheet", 
        "href='data:text/css,' type='text/css'");
    document.insertBefore(xs, document.rootElement);
    xs.sheet.insertRule("circle{fill:blue;}", 0); 
    

    您不清楚为什么要尝试动态创建样式表。如果目的是实际链接到同域服务器上的有效样式表,那么安全问题就不会成为问题;问题是数据 URI 被视为跨域。

  3. 使用 svg:style 元素,然后使用 document.styleSheets 访问样式表对象(从 cmets 到另一个答案,看来这就是您已经在做的事情)。循环浏览所有样式表,直到找到将您的样式元素作为所有者节点的样式表:

    var ss = document.createElementNS("http://www.w3.org/2000/svg", "style");
    svgElement.appendChild(ss);
    var sheets = document.styleSheets,
        sheet;
    for(var i=0, length=sheets.length; i<length; i++){
       sheet=sheets.item(i);
       if (sheet.ownerNode == ss) break;
    }
    sheet.insertRule("circle{fill:green;}", 0);
    

    无论您的 SVG 是否在独立文件中,这都应该有效。

【讨论】:

  • 感谢 AmeliaBR,这是对当前状态的一个很好的解释。 (实际上我现在只是添加文本节点。insertRule 的优点是您可以稍后删除规则,但我重新设计了一些东西以避免这种情况。)
  • 你也可以ss.innerHTML = "circle{fill:green;}"
  • @CharlesL。这应该适用于大多数现代浏览器,但请注意,SVG 命名空间元素不支持 innerHTML 属性。但是,您可以使用 ss.textContent 达到相同的效果,因为无论如何您都没有解析 HTML 元素。
【解决方案2】:

您可以在svg 元素内使用style 节点。

来自 MDN 的示例:

<svg width="100%" height="100%" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg">
  <style>
    /* <![CDATA[ */
    circle {
      fill: orange;
      stroke: black;
      stroke-width: 10px;
    }
    /* ]]> */
  </style>

  <circle cx="50" cy="50" r="40" />
</svg>

您可以像在 HTML 中那样添加它们。

var style = document.createElement('style');
style.setAttribute("type", "text/css");
var svg = document.getElementsByTagName("svg")[0];
svg.appendChild(style);

【讨论】:

  • 谢谢乔纳森,我知道了。但我想从 javascript 创建它们。请看我的问题!
  • 再次感谢乔纳森,但我在示例中做到了。我想做的是访问工作表(通常是样式元素的属性)。然而我做不到。然后我不能操纵这张纸。 (我可以,但不是我想要的方式!)
  • 从来没有听说过sheet 属性tbh,你的意思是document.styleSheets
  • 您可以像这样通过 textContent 属性访问样式描述。 theStyle.textContent = "svg{背景色:蓝色;}";
  • @Jonathan,它是一样的,但sheet 是来自style 元素的链接。当它起作用时。 ;-)
【解决方案3】:

IE11 的 SVGStyleElements 中缺少“sheet”属性
根据 AmeliaBR 的回答,我做了一个 polyfill:

if (!('sheet' in SVGStyleElement.prototype)) {
    Object.defineProperty(SVGStyleElement.prototype, 'sheet', {
        get:function(){
            var all = document.styleSheets;
            for (var i=0, sheet; sheet=all[i++];) {
                if (sheet.ownerNode === this) return sheet;
            }

        }
    });
}

【讨论】:

    猜你喜欢
    • 2013-09-12
    • 1970-01-01
    • 2016-03-07
    • 2012-11-20
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    相关资源
    最近更新 更多