不同位置的多个 Use 元素上的 SVG ClipPath

标签 svg clipping

直到最近,以下 SVG 代码都可以在 Firefox (v25) 中正确呈现,但现在不再正确呈现 (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 的位置,而不是将其视为相对于它的位置,那么我看不出如何在多个元素中重用剪辑。

最佳答案

默认情况下,剪切路径的位置是在应用该路径的对象的用户坐标系 ( clipPathUnits="userSpaceOnUse" ) 中计算的。

(您可以将其设置为 clipPathUnits="objectBoundingBox" ,但随后您必须重新定义剪切路径中形状的所有长度,使其相对于被剪切形状的高度和宽度。)

有一个简单的解决方案可以始终获得您想要的效果:转换使用元素的坐标系。而不是使用 x 来定位它们和y属性,将它们定位为 transform="translate(x,y)"属性。这样,用于定位剪切路径的坐标系将随之移动。

Here's your fiddle updated to show the change 。下面以堆栈片段的形式重复它,并且应该在所有浏览器中按预期工作。

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

    

<小时/>

那么当您使用 x应该发生什么和y而不是transform ?很难说,因为规范不一致。

从剪切路径规则的逻辑应用来看,Firefox (v33) 的实现是有意义的。 当你 <use>一个<symbol> ,您为符号内的内容创建一个新的坐标空间,但使用元素仍位于父坐标空间中。由于正在剪切的是 use 元素,因此该坐标对于与剪切路径匹配很重要。 x 坐标为 50 或更大的 use 元素将始终位于您指定的剪切路径之外,且不会超出 x=30。

但是,为什么其他浏览器将剪切路径原点定位在 <use>元素的 (x,y) 点而不是其坐标系的原点?这是因为the way the specifications define how x and y should be implemented :作为添加到分组元素的附加转换,该分组元素还具有您在 clip-path 上指定的所有其他属性和样式(包括 <use> ) .

根据规范,代码如下:

<use xlink:href="#content" clip-path="url(#clip)" 
     x="50" y="100" width="50" height="100" />

应该渲染(假设“内容”是 <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属性。

但是,这与使用 <image> 时发生的情况完全不同。或<rect>而不是<use> ,但具有完全相同的 x , y , width , heightclip-path属性。对于这些其他元素,xy仅定义父坐标系内的位置,而不是坐标系的变换,因此它们确实会更改剪切路径的原点。这就是为什么我将其称为规范中不幸的不一致。

关于不同位置的多个 Use 元素上的 SVG ClipPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26725911/

相关文章:

html - CSS 并在悬停时更改 SVG 图标

iphone - 填充 CGPath 的逆值而不进行裁剪

math - 如何在平截头体上剪切线段?

java - 剪线最优雅的方式?

jquery 在 svg 圆圈下方显示 div

css - IE 不将 SVG 显示为伪元素 :before or :after 中的内容

css - FF25 和 IE10 中的内嵌 SVG 边框为 1px(或更小?亚像素?),Chrome 除外

OpenGL 近剪裁平面

CSS Clip-path定位问题