在不同位置使用多个Use元素的SVG clipPath

3

最近,在Firefox(v25)中以下SVG代码能够正确地呈现,但是在新版本Firefox(v33)中无法正确呈现。而我测试过的所有其他浏览器均可正常显示(Chrome 33,Safari 6,IE 10)。

http://jsfiddle.net/9btoveeL/

<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="1000px" width="1000px" y="0px" x="0px" version="1.1">
<defs>
    <clipPath id="clip1">
        <rect height="100" width="10" y="0" x="0"/>
    </clipPath>
    <clipPath id="clip2">
        <rect height="100" width="10" y="0" x="10"/>
    </clipPath>
    <clipPath id="clip3">
        <rect height="100" width="10" y="0" x="20"/>
    </clipPath>
    <symbol id="fill_texture">
        <g>
            <rect height="10" width="10" x="0" y="0" fill="#ff0000"/>
            <rect height="10" width="10" x="3" y="5" fill="#0ff000"/>
            <rect height="10" width="10" x="6" y="10" fill="#0000ff"/>
            <rect height="10" width="10" x="9" y="15" fill="#ffff00"/>
            <rect height="10" width="10" x="12" y="20" fill="#ff00ff"/>
            <rect height="10" width="10" x="15" y="25" fill="#00ffff"/>
        </g> 
    </symbol>
</defs>
<g id="columns">
    <use id="unclipped" xlink:href="#fill_texture" width="100" height="100" x="0" y="0"/>


    <use id="slot1" xlink:href="#fill_texture" clip-path="url(#clip1)" x="50" y="0"/>
    <use id="slot2" xlink:href="#fill_texture" clip-path="url(#clip2)" x="100" y="0"/>
    <use id="slot3" xlink:href="#fill_texture" clip-path="url(#clip3)" x="150" y="0"/>
</g>    
</svg>

我尝试的是将一个准备好的符号切成三个部分,然后在任何我想要的地方使用这三个部分。在Firefox 33中,它似乎将剪辑应用于其原始位置(在我的示例中为0,0或0,10),而其他浏览器和先前版本的Firefox则从应用于其的use元素的左上角开始应用剪辑。 如果每个剪辑路径必须移动以匹配use的位置,而不是相对于它进行处理,我看不出如何在多个元素中重复使用剪辑。

通过 https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=SVG 在 Bugzilla 上提出一个 bug,并尝试使用 http://mozilla.github.io/mozregression/ 找到比 25 到 33 之间更好的回归范围。 - Robert Longson
1个回答

5
默认情况下,剪切路径的位置是根据应用于其上的对象的用户坐标系计算的(clipPathUnits="userSpaceOnUse")。(您可以将其设置为clipPathUnits="objectBoundingBox",但这样就必须重新定义剪切路径内形状的所有长度相对于被裁剪的形状的高度和宽度。)有一个简单的解决方案,可始终获得所需效果:转换用元素的坐标系。使用xy属性定位它们的位置,而是使用transform="translate(x,y)"属性定位它们的位置。这样,用于定位剪切路径的坐标系将随它们一起移动。这里是更新后的演示。在下面的堆栈片段中重复显示,并应在所有浏览器中按预期工作。

<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" 
     xml:space="preserve" version="1.1"
     height="100px" width="400px" y="0px" x="0px" >
<defs>
 <clipPath id="clip1" >
  <rect height="100" width="10" y="0" x="0"/>
 </clipPath>
 <clipPath id="clip2">
  <rect height="100" width="10" y="0" x="10"/>
 </clipPath>
 <clipPath id="clip3">
  <rect height="100" width="10" y="0" x="20"/>
 </clipPath>
 <symbol id="fill_texture">
  <g>
   <rect height="10" width="10" x="0" y="0" fill="#ff0000"/>
   <rect height="10" width="10" x="3" y="5" fill="#0ff000"/>
   <rect height="10" width="10" x="6" y="10" fill="#0000ff"/>
   <rect height="10" width="10" x="9" y="15" fill="#ffff00"/>
   <rect height="10" width="10" x="12" y="20" fill="#ff00ff"/>
   <rect height="10" width="10" x="15" y="25" fill="#00ffff"/>
  </g> 
 </symbol>
</defs>
<g id="columns">
 <use id="unclipped" xlink:href="#fill_texture"  
         width="100" height="100" x="0" y="0"/>
 
 
 <use id="slot1" xlink:href="#fill_texture" clip-path="url(#clip1)"  
         transform="translate(50,0)"/>
 <use id="slot2" xlink:href="#fill_texture" clip-path="url(#clip2)" 
         transform="translate(100,0)"/>
 <use id="slot3" xlink:href="#fill_texture" clip-path="url(#clip3)"   
         transform="translate(150,0)"/>
</g> 
</svg>

    


当您使用xy而不是transform时,会发生什么?很难说,因为规范存在不一致性。Firefox(v33)的实现从剪切路径规则的逻辑应用角度讲得通。当您<use>一个<symbol>时,您为符号内的内容创建了一个新的坐标空间,但use元素仍在父坐标空间中。由于正在被裁剪的是use元素,因此匹配裁剪路径所需考虑的是该坐标。x坐标为50或更高的use元素将始终位于您给出的不超过x = 30的裁剪路径之外。
但是,为什么其他浏览器将裁剪路径原点定位在<use>元素的(x,y)点而不是其坐标系的原点呢?这是因为规范如何定义应该实现xy的方式:作为添加到分组元素中的附加变换,该分组元素还具有您在<use>上指定的所有其他属性和样式(包括clip-path)。
根据规范,以下代码:
<use xlink:href="#content" clip-path="url(#clip)" 
     x="50" y="100" width="50" height="100" />

假设“content”是一个<symbol>,则应该呈现为相同的内容。
<g clip-path="url(#clip)" transform="translate(50,100)">
    <svg width="50" height="100" <!--viewBox and other attributes from the symbol--> >
       <!-- graphics from symbol#content go here -->
    </svg>
</g>

根据此表示,剪辑路径应该被翻译以匹配transform属性。然而,如果您使用

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