Javascript 如何为SVG元素创建样式表?
我尝试向SVG元素添加样式表,如下所示:Javascript 如何为SVG元素创建样式表?,javascript,dom,svg,stylesheet,Javascript,Dom,Svg,Stylesheet,我尝试向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.she
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
我应该怎么做才能到达样式中的图纸节点
这里有一把小提琴:您可以在
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>
正如@RobertLongson在评论中指出的那样,问题在于,它没有实现 以下是一些变通方法(在等待SVG2规范实现最新的CSS OM规范时):
元素来设置SVG的样式。只需确保在默认名称空间中创建样式元素,或者在XHTML名称空间中显式创建样式元素,以便获得的是而不是SVGStyleElement
的实例
将新创建的HTMLStyleElement添加到文档的头部,将为您创建CSS样式表对象:
var hs = document.createElement("style");
hs.type = "text/css";
document.head.insertBefore(hs, null);
hs.sheet.insertRule("circle{fill:red;}", 0);
元素不同,处理指令节点必须链接到文件,否则浏览器将永远不会初始化样式表对象。我试图通过将外部文件定义为正确MIME类型的空数据URI来解决这个问题当从控制台运行时,它通常(但不一致)在FF/Chrome中工作,但不是从嵌入式脚本运行。在Chrome中,sheet
属性始终为空,就像Chrome处理跨域样式表一样;Firefox给出了一个明确的安全错误。我假设它在IE中根本不起作用,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被视为跨源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);
var ss=document.createElements(“http://www.w3.org/2000/svg“,”风格“);
附肢儿童(ss);
var sheets=document.styleSheets,
床单;
对于(var i=0,length=sheets.length;iIE11中的SVGStyleElements中缺少“sheet”属性
根据AmeliaBR的回答,我做了一个polyfill:
if(!('sheet'在SVGStyleElement.prototype中)){
Object.defineProperty(SVGStyleElement.prototype,“sheet”{
get:function(){
var all=document.styleSheets;
对于(变量i=0,工作表;工作表=all[i++];){
如果(sheet.ownerNode==此)返回工作表;
}
}
});
}
谢谢Jonathan,我知道。但我想从javascript创建它们。请看我的问题!再次感谢Jonathan,但我在我的示例中做到了。我想做的是访问工作表(通常是样式元素的属性)。但是我不能。然后我不能操作工作表。(我可以,但不是我想要的方式!)从来没有听说过sheet
属性tbh,你的意思是document.styleSheets
?你可以像这样通过textContent属性访问样式描述。theStyle.textContent=“svg{background color:blue;}”@Jonathan,它是一样的,但是sheet
是来自style
元素的链接。当它起作用时;-)请通过联系w3c svg工作组,并要求他们将其添加到SVG2规范中。谢谢,@RobertLongson。完成。下面是导致规范编辑操作的线程:。我刚刚推送了将LinkStyle(又称图纸访问器)添加到SVGStyleElement的更新。要在Blink(Opera/Chrome)中跟踪此功能的实现,请参阅。@ErikDahlström很高兴看到许多peeople人在合作!谢谢AmeliaBR,这是对当前状态的一个很好的解释。(实际上我现在只添加文本节点。insertRule的优点是您可以稍后删除该规则,但为了避免这种情况,我重新设计了一些东西。)您也可以执行ss.innerHTML=“circle{fill:green;}”
@CharlesL。这在大多数现代浏览器中都应该适用,但要注意,SVG命名空间元素不支持innerHTML
属性。但是,您可以使用ss.textContent
达到相同的效果,因为您无论如何都不会解析HTML元素。
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);