本文由大漠根據SaraSoueidan的《Clipping in CSS and SVG – The clip-path Property and <clipPath> Element》所譯,整個譯文帶有我們自己的理解與思想,如果譯得不好或有不對之處還請同行朋友指點。如需轉載此譯文,需注明原作者相關信息http://sarasoueidan.com/blog/css-svg-clipping/。
——作者:SaraSoueidan
——譯者:大漠
CSS和SVG有很多共同之處。CSS有很多特性都是從SVG中引入過來的。其中就有“剪切”的特性。CSS和SVG都允許我們對一個元素進行非矩形的剪切。在這篇文章中,將介紹CSS和SVG中的剪切技術。
特別聲明:本文提供的DEMO可能在你的瀏覽器中不能正常的演示,你應該查看這個表格了解更多相關的信息。你在閱讀這篇文章之時沒有必要查看提供的DEMO。不是所有的剪切特性都可以實現或者說只能實現部分剪切特性。本文的最大目的是告訴你CSS和SVG中的剪切是如何工作?僅用來做為參考。在文章中的代碼不帶有任何瀏覽器的私有前綴,但在示例中還是帶了瀏覽器的私有前綴。
剪切是什么
剪切是一個圖形化操作,你可以部分或者完全隱藏一個元素。被剪切的元素可以是一個容器也可以是一個圖像元素。元素的哪些部分顯示或隱藏是由剪切的路徑來決定的。

剪切路徑定義了一個區域,在這個區域內的內容將會顯示,而不在這個區域內的內容不會顯示。這個區域被稱之為“裁剪區域”。只要在這個區域之外的任何元素都不會顯示。包括元素的內容、背景、邊框、文本、輪廓等,甚至還包括他的子元素。
剪切的元素可以是任何容器和圖片元素。
剪切路徑的概念就相當於在元素上定義了一個視窗。它決定了元素哪些部分在這個“視窗”中顯示,哪些部分不在這個“視窗”中顯示。但他不會影響自身文檔流和其他文檔流,因為他通常還是以一個矩形區域顯示在其他文檔流前面,哪怕是剪切出來的區域是不規則的矩形。如果你想改變周圍內容元素圍繞剪切出來的圖形,那就需要使用CSS的圖形屬性。如果你對這方面知識感興趣,可以閱讀我早前寫的相關文章。
有關於CSS3 Shapes相關中文教程,可以閱讀早前翻譯的兩篇文章:
CSS中的剪切——clip-path屬性
clip-path屬性是CSS Masking模塊的一部分。自從2000年以來,剪切都只是SVG中的一部分,現在將這個功能引入到CSS的Msking模塊中,所以現在可以對HTML元素和SVG元素進行剪切。
clip-path屬性是指定一個應用到元素上的剪切路徑。應用在SVG中<clipPath>元素上的屬性值可以完全運用在clip-path的屬性上。你還可以使用CSS Shapes模塊中的基本形狀來定義剪切路徑。這些形狀你可以使用形狀函數來創建。這些形狀態函數包括polygon()、circle()、inset()(用來定義嵌入的矩形)和ellipse()。
使用clip-path屬性將一個剪切路徑運用在一個元素上非常的簡單:
/* SVG中的clipPath的使用 */ .element { clip-path: url(#svgClipPathID); } /* 使用CSS中的基本圖形函數 */ .element { clip-path: polygon(...); /* 或者其他的圖形函數 */ }
例如,我們使用polygon()函數定義一個多邊形的剪切路徑,並且把這個路徑應用到一個圖像上,代碼看起來像這樣:
img { clip-path: polygon(626px 463px,765px 236px,687px 31px,271px 100px,70px 10px,49px 250px,133px 406px,374px 462px,529px 393px); }
應用上面的代碼之后,圖像顯示成這樣:
基本圖形函數允許我們創建一定數量的圖形,其中最復雜的就是多邊形。如果你想創建一個更為復雜的圖形,而且圖形看起來不是用直線畫出來的,這個時候你就需要使用SVG的<clipPath>元素。正如<clipPath>元素名稱所暗示的一樣,你可以使用這個元素繪制任意路徑的圖形。這也意味着,你可以使用<clipPath>元素繪制出任意圖形來做為一個剪切路徑。
在我們第二個示例中,使用SVG的clipPath定義一個路徑,這個剪切路徑看起來像這樣:
<svg height="0" width="0"> <defs> <clipPath id="svgPath"> <path fill="#FFFFFF" stroke="#000000" stroke-width="1.5794" stroke-miterlimit="10" d="M215,100.3c97.8-32.6,90.5-71.9,336-77.6 c92.4-2.1,98.1,81.6,121.8,116.4c101.7,149.9,53.5,155.9,14.7,178c-96.4,54.9,5.4,269-257,115.1c-57-33.5-203,46.3-263.7,20.1 c-33.5-14.5-132.5-45.5-95-111.1C125.9,246.6,98.6,139.1,215,100.3z"/> </clipPath> </defs> </svg>
這剪切路徑看起來就像一個黑色的描邊圈了一個不規則的圖形,這是一個簡單的剪切路徑,不帶有任何的填充。

在下一部分中,我們將着重討論SVG的<clipPath>元素。但現在,我們來看看如何將定義好的路徑運用到圖片上:
img { clip-path: url(#svgPath); }
最終效果如下所示:
事實上,<clipPath>元素包括很多個基本圖形(<rect>,<circle>等),<path>元素,甚至是<text>元素。
如果在<clipPath>里面通過<text>指定文本,那么這個文本就會當成是一個剪切路徑,不管文是否可見,文本外的區域都將被剪切掉。
注意,你可以使用任何文本做為剪切路徑。這為實現很多效果開啟了一扇大門。你可以使用動畫圖片(比如,gif),甚至是視頻,然后選擇你需要的文本進行剪切。這里是沒有任何限制的。
下面的示例,就是使用文本做為剪切路徑:
<svg height="0" width="0"> <defs> <clipPath id="svgTextPath"> <text x="0" y="300" textLength="800px" lengthAdjust="spacing" font-family="Vollkorn" font-size="230px" font-weight="700" font-style="italic"> Blossom </text> </clipPath> </defs> </svg>
SVG中的<text>最酷的特點就是可以使用自定義字體,就像HTML文本。在我們的示例中使用了Google Web Fonts中的Vollkorn字體。使用textLength屬性,將文本的寬度設置的和圖片寬度一樣, 並且通過x和y來定位文本。注意,x和y坐標確認了文本左下角的位置(也就是文本的基線baseline)。
使用上面的文本路徑剪切圖來的圖片效果如下:
正如我們前面提到的,你還可以在<clipPath>中使用多個圖形形狀。在下一節中,將會深入介紹<clipPath>,這里我們先簡單的了解。在這個示例中,我們使用了多個<circle>形狀,他們大小不同,位置不同。
<svg height="0" width="0"> <defs> <clipPath id="svgPath"> <circle stroke="#000000" stroke-miterlimit="10" cx="50" cy="50" r="40" /> <circle stroke="#000000" stroke-miterlimit="10" cx="193.949" cy="235" r="74.576"/> <circle stroke="#000000" stroke-miterlimit="10" cx="426.576" cy="108.305" r="47.034"/> <circle stroke="#000000" stroke-miterlimit="10" cx="346.915" cy="255.763" r="43.644"/> <circle stroke="#000000" stroke-miterlimit="10" cx="255.39" cy="82.882" r="35.17"/> <!-- more circles... --> </clipPath> </defs> </svg>
此時,圖像只會在圓中顯示,圓外就不會顯示:
正如我們這篇文章中介紹的,你可以使用clip-path屬性應用在SVG元素繪制的路徑。在上面演示的示例,剪切路徑都是應用在HTML中的<img>元素上。在接下來的示例中,將演示的是一個剪切路徑用於<svg>的根元素。同樣是櫻花圖片,使用下面SVG的中的<image>來引用。
SVG中的<image>元素用來引用一個完整的SVG或像素圖像。如果你在<image>中引用的SVG圖像,設置的width和height屬性,將會用來設置SVG視窗的大小。如果你引用的是像素圖像(我們這里的例子就是這樣做的),圖像將會自動縮放到指定的width和height。所以我們要確認好他們的長寬比例,避免圖像扭曲。
當你創建一個SVG時,你可以在<svg>元素上指定其寬度和高度的大小,用於創建一個窗口。任何超過這個窗口的內容都將不會顯示出來。你可以通過<clipPath>元素定制一個窗口。
<svg height="500" width="800"> <image xlink:href="flowers.jpg" x="0" y="0" width="800" height="500"/> <defs> <clipPath id="theSVGPath"> <rect x="0" y="0" stroke="#000000" stroke-miterlimit="10" width="108" height="500"/> <rect x="121.5" y="25.5" stroke="#000000" stroke-miterlimit="10" width="55" height="455"/> <rect x="192.5" y="9.5" stroke="#000000" stroke-miterlimit="10" width="60" height="484"/> <rect x="271.5" y="44.5" stroke="#000000" stroke-miterlimit="10" width="63" height="416"/> <rect x="349.5" y="25.5" stroke="#000000" stroke-miterlimit="10" width="208" height="447"/> <rect x="574.5" y="44.5" stroke="#000000" stroke-miterlimit="10" width="60" height="446"/> <rect x="644.5" y="9.5" stroke="#000000" stroke-miterlimit="10" width="68" height="471"/> <rect x="736.5" y="18.5" stroke=



