繁体   English   中英

如何为 SVG 元素创建样式表?

[英]How do I create a style sheet for an SVG element?

我尝试向 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/

正如@RobertLongson 在评论中指出的那样,问题在于SVG 规范定义了一个svg:style element interface ,但它没有实现与样式表的 owner element 相关联的 CSS OM 接口

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

  1. 使用 (X)HTML 样式元素。 如果您的 SVG 代码内嵌在 (X)HTML 文档中,则 HTML <style>元素可用于设置 SVG 的样式。 只需确保在默认命名空间中创建 style 元素或在 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);

    这个答案更详细地介绍了在 HTML 中动态创建样式表,包括一个工作示例。

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

    但是,与可以为空的<style>元素不同,处理指令节点必须链接到文件,否则浏览器将永远不会初始化样式表对象。 我试图通过将外部文件定义为正确 MIME 类型的空数据 URI 来解决这个问题。 从控制台运行时,它通常但不始终如一地在 FF/Chrome 中运行,但不能从嵌入式脚本运行。 在 Chrome 中, sheet属性始终为 null,与 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访问样式表对象(从注释到另一个答案,这似乎是您已经在做的)。 循环浏览所有样式表,直到找到将样式元素作为所有者节点的样式表:

     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 是否在独立文件中,这都应该有效。

您可以在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);

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;
            }

        }
    });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM