更改使用元素中defs中定义的属性

时间:2011-02-21 17:13:52

标签: svg

如何通过脚本来改变defs中定义的“use元素”的样式?我试图进入w3c工作草案接口,但我迷失在那个迷宫中

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<svg
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   xmlns="http://www.w3.org/2000/svg"
   version="1.1"
   width="100"
   height="100"
   id="svg1">

<defs>
   <g id="minchia" onclick="color(evt)">
     <rect width="50" height="50" style="fill:#ffff6e;stroke:#ee1400;stroke-width:3" />
   </g>
</defs>       

<script type="text/javascript"> 
<![CDATA[ 
function color(evt)
{   
    node = evt.target.correspondingUseElement;

    alert(node.getAttributeNS(null, "style"));   /* empty! */
    alert(node.getAttributeNS("http://www.w3.org/1999/xlink", "style"));   /* empty! */

    node.setAttributeNS("http://www.w3.org/1999/xlink", "fill", "blue");    /* nothing */
    node.setAttributeNS(null, "fill", "blue");  /* nothing */
}
]]> 
</script>

<use xlink:href="#minchia" id="frufru" x="10" y="10"  />       
</svg>

更新

还有一件事:如果引用的元素是包含2个其他元素的“g”,如rect和text,该怎么办?如何为正确的childNode设置属性(通过DOM方法)? 在此示例中,setAttribute正在为引用元素的第一个子元素设置样式。如果我必须设计第二个样式怎么办?

<?xml version="1.0" encoding="UTF-8" standalone="no"?>

<svg
  xmlns:svg="http://www.w3.org/2000/svg"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns="http://www.w3.org/2000/svg"
  version="1.1"
  width="1000"
  height="1000"
  id="svg1">

<defs>
  <g id="test" onclick="color(evt)" >
 <rect
   width="54"
   height="58"
   x="1.5"
   y="1.5"
   id="rect5" />
<text
   x="-34"
   y="47"
   transform="matrix(0.66777386,-0.74436421,0.74436421,0.66777386,0,0)"
   id="text2987"
   style="font-size:30px;fill:#ffffff;stroke-width:0px">JC!</text>
 </g>
</defs>       

<script type="text/javascript"> 
<![CDATA[ 
function color(evt)
{   
node = evt.target.correspondingUseElement;
    node.setAttributeNS(null, "style", "fill:blue");    
}
]]> 
</script>

<use xlink:href="#test" id="frufru" x="10" y="10" style="fill:#000000" />       

</svg>

3 个答案:

答案 0 :(得分:36)

正如您在my test page中所看到的,如果您在文档的<defs>部分中定义元素的视觉样式,则无法覆盖<use>实例上的该样式,而不是应用于style的可视属性<use>属性或CSS类。

Snapshot of test results from linked SVG file, showing that only unstyled elements can be overridden

此外,您无法在<use>元素上使用视觉属性将样式级联到源的元素;你必须使用CSS样式。

你必须:

  1. 确保您定义的元素没有应用视觉样式,并且
  2. 使用CSS或设置手动解析或创建的style属性,例如

    node.setAttribute('style','fill:blue');
    
  3. 作为noted here,您可以使用setAttribute(...)setAttributeNS(null,...)获取SVG属性。

    更新:回答第二个问题:

      

    如果引用的元素是包含2个其他元素的“g”,如rect和文本,该怎么办?

    您不能使用CSS规则来选择<use>的伪子项;他们根本就不存在。但是,您可以执行的是在<def>内应用要保留的不变样式,然后在style上应用所需的<use>

    例如:

    <defs>
      <g id="foo">
        <!-- Every rect instance should be filled with blue -->
        <rect width="54" height="58" x="1.5" y="1.5"
              fill="blue" />
        <!-- I want to be able to change text color per use
             so I must be sure not to specify the fill style -->
        <text x="-34" y="47" transform="matrix(0.668,-0.744,0.744,0.668,0,0)"
         style="font-size:30px;stroke-width:0px">JC!</text>
      </g>
    </defs>
    <use xlink:href="#foo" style="fill:orange" transform="translate(0,-100)" />
    <use xlink:href="#foo" style="fill:yellow" transform="translate(0, 100)" />
    

    仅当您希望所有可更改项目的属性设置方式相同时,此方法才有效。

    与HTML不同,SVG 中的标记是演示文稿。我上面提到的是一些正常工作的hack,但通常<use>元素被设计为实例化定义的完整外观。如果您需要每个实例的自定义外观,也许您应该考虑克隆元素,修改属性,并将其添加到文档中,而不是攻击<use>

答案 1 :(得分:1)

要添加到@Phrogz答案,看起来即使我尝试覆盖symbol标记内定义的样式,它也不会在use标记中被覆盖。那个http://jsfiddle.net/rajkamal/xrdgf/

的小提琴

答案 2 :(得分:0)

如今,多亏CSS variables和一些聪明的<div>嵌套,它才可以实现。
看看我的CodePen here

诀窍是将SVG包含在div中,并在嵌套的<style>标签中设置样式变量:

<div class="svg-container">
  <svg viewBox="0 0 30 10" xmlns="http://www.w3.org/2000/svg">
    <style>
      div.svg-container {
        --stroke: red;
        --fill: blue;
      }
    </style>
    <circle id="myCircle" cx="5" cy="5" r="4" style="stroke:var(--stroke);fill:var(--fill);"/>
  </svg>
</div>

<div class="svg-container circle-1">
  <svg viewBox="0 0 30 10"  xmlns="http://www.w3.org/2000/svg">  
    <use href="#myCircle" x="10"/>
  </svg>
</div>

是否注意到这里的样式规则指向div.class
现在,在CSS文件中,您可以制定一个更具体的规则,指向容器内的<svg>

.circle-1 svg {
  --stroke: yellow;
  --fill: salmon;
}

注意:我做了实验才能使它起作用,这很棘手;-)