2018-09-16_svgPart2_transform

理解SVG坐標(biāo)系和變換(第二部分)transform

(本文轉(zhuǎn)自w3cplus斩例,這里僅修正了部分個(gè)人認(rèn)為翻譯不恰當(dāng)之處;下面是譯文鏈接奸焙,英文原文鏈接在結(jié)尾處提供)

SVG元素可以通過(guò)縮放蜻底,移動(dòng),傾斜和旋轉(zhuǎn)來(lái)變換-類似HTML元素使用CSS transform來(lái)變換聘鳞。然而薄辅,當(dāng)涉及到坐標(biāo)系時(shí)這些變換所產(chǎn)生的影響必然有一定差別要拂。在這篇文章中我們討論SVG的transform屬性和CSS屬性,包括如何使用站楚,以及你必須知道的關(guān)于SVG坐標(biāo)系變換的知識(shí)宇弛。

這是我寫(xiě)的SVG坐標(biāo)系統(tǒng)和變換部分的第二篇。在第一篇中源请,包括了任何要理解SVG坐標(biāo)系統(tǒng)基礎(chǔ)的需要知道的內(nèi)容;更具體的是彻况, SVG viewport, viewBox 和 preserveAspectRatio 屬性谁尸。

這一部分我建議你先閱讀第一篇,如果沒(méi)有纽甘,確保你在閱讀這篇之前已經(jīng)讀了第一篇良蛮。

transform屬性值

tranform屬性用來(lái)對(duì)一個(gè)元素指定一個(gè)或多個(gè)變換。它將<transform-list>作為一個(gè)值悍赢,該值被定義為轉(zhuǎn)換定義的列表决瞳,按照提供的順序應(yīng)用。每個(gè)變換定義由空格或逗號(hào)隔開(kāi)左权。給元素添加變換看起來(lái)如下:

有效地SVG變換有:旋轉(zhuǎn)(rotation), 縮放(scaling), 移動(dòng)(translation), 和傾斜(skewing)皮胡。transform屬性中使用的變換函數(shù)類似于CSS中transform屬性使用的CSS變換函數(shù)碟贾,除了參數(shù)不同栓始。

注意下列的函數(shù)語(yǔ)法定義只在transform屬性中有效。查看section about transforming SVGs with CSS properties獲取關(guān)于CSS變換屬性中使用的語(yǔ)法信息竟贯。

Matrix

你可以使用matrix()函數(shù)在SVG元素上添加一個(gè)或多個(gè)變換锌杀。matrix變換語(yǔ)法如下:

matrix(<a> <b> <c> <d> <e> <f>)

上述聲明通過(guò)一個(gè)有6個(gè)值的變換矩陣聲明一個(gè)變換甩栈。matrix(a,b,c,d,e,f)等同于添加變換matrix[a b c d e f]。

如果你不精通數(shù)學(xué)糕再,最好不要用這個(gè)函數(shù)量没。對(duì)于那些精通的人,你可以在這里閱讀更多關(guān)于它背后的數(shù)學(xué)內(nèi)容突想。因此這個(gè)函數(shù)很少使用-我將忽略來(lái)討論其他變換函數(shù)殴蹄。

Translation

要移動(dòng)SVG元素,你可以用translate()函數(shù)蒿柳。translate函數(shù)的語(yǔ)法如下:

translate(<tx> [<ty>])

translate()函數(shù)輸入一個(gè)或兩個(gè)值得來(lái)聲明水平和豎直移動(dòng)值饶套。tx代表x軸上的translation值;ty代表y軸上的translation值垒探。

ty值是可選的妓蛮,如果省略,默認(rèn)值為0圾叼。tx和ty值可以通過(guò)空格或者逗號(hào)分隔蛤克,它們?cè)诤瘮?shù)中不代表任何單位-它們默認(rèn)等于當(dāng)前用戶坐標(biāo)系單位捺癞。

下面的例子把一個(gè)元素向右移動(dòng)100個(gè)用戶單位,向下移動(dòng)300個(gè)用戶單位构挤。

<circlecx="0" cy="0" r="100" transform="translate(100 300)" />

上述代碼如果以translate(100, 300)用逗號(hào)來(lái)分隔值的形式聲明一樣有效髓介。

Scaling

你可以通過(guò)使用scale()函數(shù)變換來(lái)向上或者向下縮放來(lái)改變SVG元素的尺寸。scale變換的語(yǔ)法是:

scale(<sx> [<sy>])

scale()函數(shù)輸入一個(gè)或兩個(gè)值來(lái)聲明水平和豎直縮放值筋现。sx代表沿x軸的縮放值唐础,用來(lái)水平延長(zhǎng)或者拉伸元素;sy代表沿y軸縮放值矾飞,用來(lái)垂直延長(zhǎng)或者縮放元素一膨。

sy值是可選的,如果省略默認(rèn)值等于sx洒沦。sx和sy可以用空格或者逗號(hào)分隔豹绪,它們是無(wú)單位值。

下面例子把一個(gè)元素的尺寸根據(jù)最初的尺寸放大兩倍:

<rect width="150" height="100" transform="scale(2)" x="0" y="0" />

下列例子把一個(gè)元素縮放到最初寬度的兩倍申眼,并且把高度壓縮到最初的一半:

<rect width="150" height="100" transform="scale(2 0.5)" x="0" y="0" />

上述例子使用逗號(hào)分隔的值例如scale(2, .5)仍然有效瞒津。

這里需要注意當(dāng)SVG元素縮放時(shí),整個(gè)坐標(biāo)系被縮放括尸,導(dǎo)致元素在視窗中重新定位巷蚪,現(xiàn)在不用擔(dān)心這些,我們會(huì)在下一節(jié)中討論細(xì)節(jié)姻氨。

Skew

SVG元素也可以被傾斜钓辆,要傾斜一個(gè)元素,你可以使用一個(gè)或多個(gè)傾斜函數(shù)skewX 和 skewY肴焊。

skewX(<skew-angle>)
skewY(<skew-angle>)

函數(shù)skewX聲明一個(gè)沿x軸的傾斜前联;函數(shù)skewY聲明一個(gè)沿y軸的傾斜。

傾斜角度聲明是無(wú)單位角度的默認(rèn)是度娶眷。

注意傾斜一個(gè)元素可能會(huì)導(dǎo)致元素在視窗中重新定位似嗤。在下一節(jié)中有更多細(xì)節(jié)。

Rotation

你可以使用rotate()函數(shù)來(lái)旋轉(zhuǎn)SVG元素届宠。這個(gè)函數(shù)的語(yǔ)法如下:

rotate(<rotate-angle> [<cx> <cy>])

rotate()函數(shù)對(duì)于給定的點(diǎn)和旋轉(zhuǎn)角度值執(zhí)行旋轉(zhuǎn)烁落。不像CSS3中的旋轉(zhuǎn)變換,不能聲明除degress之外的單位豌注。角度值默認(rèn)無(wú)單位伤塌,默認(rèn)單位是度。

可選的cx和cy值代表無(wú)單位的旋轉(zhuǎn)中心點(diǎn)轧铁。如果沒(méi)有設(shè)置cx和cy每聪,旋轉(zhuǎn)點(diǎn)是當(dāng)前用戶坐標(biāo)系的原點(diǎn)(查看第一部分如果你不知道用戶坐標(biāo)系是什么。)

在函數(shù)rotate()中聲明旋轉(zhuǎn)中心點(diǎn)一個(gè)快捷方式類似于CSS中設(shè)置transform: rotate()和transform-origin。SVG中默認(rèn)的旋轉(zhuǎn)中心是當(dāng)前使用的用戶坐標(biāo)系的左上角药薯,這樣也許你無(wú)法創(chuàng)建想要的旋轉(zhuǎn)效果绑洛,你可以在rotate()中聲明一個(gè)新的中心點(diǎn)。如果你知道元素在SVG畫(huà)布中的尺寸和定位童本,你可以把它的中心設(shè)置為旋轉(zhuǎn)中心真屯。

下面的例子是以當(dāng)前用戶坐標(biāo)系中的(50,50)點(diǎn)為中心進(jìn)行旋轉(zhuǎn)一組元素:

<g id="parrot" transform="rotate(45 50 50)" x="0" y="0">
    <!-- elements making up a parrot shape -->
</g>

然而,如果你想要一個(gè)元素圍繞它的中心旋轉(zhuǎn)穷娱,你也許想要像CSS中一樣聲明中心為50% 50%绑蔫;不幸的是,在rotate()函數(shù)中這樣做是不允許的-你必須用絕對(duì)坐標(biāo)泵额。但是晾匠,您可以使用CSS transform-origin屬性以及CSS transform屬性來(lái)實(shí)現(xiàn)這一點(diǎn)。本文稍后將對(duì)此進(jìn)行詳細(xì)介紹梯刚。

坐標(biāo)系變化

現(xiàn)在我們已經(jīng)討論了所有可能的SVG變換函數(shù),我們深入挖掘視覺(jué)部分和對(duì)SVG元素添加每個(gè)變換的效果薪寓。這是SVG變換最重要的部分亡资。因此它們被稱為“坐標(biāo)系統(tǒng)變換"而不僅僅是“元素變換”。

在這個(gè)規(guī)范中向叉,transform屬性被定義為在應(yīng)用它的元素上建立新用戶空間(當(dāng)前坐標(biāo)系統(tǒng))的兩個(gè)屬性之一——viewBox屬性是創(chuàng)建新用戶空間的兩個(gè)屬性中的第二個(gè)锥腻。那么這到底意味著什么呢?

①transform屬性在它所應(yīng)用的元素上建立一個(gè)新的用戶空間(當(dāng)前坐標(biāo)系統(tǒng))。

這個(gè)行為類似于在HTML元素上添加CSS變換-HTML元素坐標(biāo)系發(fā)生了變換母谎,當(dāng)你把變換組合使用時(shí)最明顯瘦黑。雖然在很多方面很相似,HTML和SVG的變換還是有一些不同奇唤。

主要的不同是坐標(biāo)系幸斥。HTML元素的坐標(biāo)系建立在元素自身之上。然而咬扇,在SVG中甲葬,元素的坐標(biāo)系最初(譯者注:這里是指元素被變換之前的坐標(biāo)系)是當(dāng)前坐標(biāo)系或使用中的用戶空間。

當(dāng)你在一個(gè)SVG元素上添加transform屬性懈贺,元素獲取當(dāng)前使用的用戶坐標(biāo)系的一個(gè)“副本”经窖。你可以當(dāng)做給發(fā)生變換的元素創(chuàng)建一個(gè)新“層”,新層上是當(dāng)前用戶坐標(biāo)系的副本(the viewBox)梭灿。

然后画侣,元素新的當(dāng)前坐標(biāo)系被在transform屬性中聲明的變換函數(shù)改變,因此導(dǎo)致元素自身的變換堡妒。這看起來(lái)好像是元素在變換后的坐標(biāo)系中重新繪制配乱。

要理解如何添加SVG變換,讓我們從可視化的部分開(kāi)始。下面圖片是我們要研究的SVG畫(huà)布宪卿。

svg-transforms-canvas.png

鸚鵡和小狗使我們要變換的元素(組)的诵。

<svg width="800" height="800" viewBox="0 0 800 600">
    <g id="parrot">
        <!-- shapes and paths forming the parrot -->
    </g>
    <g id="dog">
        <!-- shapes and paths forming the dog -->
    </g>
</svg>

灰色坐標(biāo)是通過(guò)viewBox建立的畫(huà)布的初始坐標(biāo)系。為了方便起見(jiàn)佑钾,我將不改變初始坐標(biāo)系-我用一個(gè)和viewport相同尺寸的viewBox西疤,如你在上述代碼中看到的一樣。

When you apply the transform attribute to an SVG element, that element gets a "copy" of the current user coordinate system in use.(當(dāng)您將transform屬性應(yīng)用到SVG元素時(shí)休溶,該元素將獲得正在使用的當(dāng)前用戶坐標(biāo)系統(tǒng)的“副本”)

現(xiàn)在我們建立了畫(huà)布和初始用戶空間代赁,讓我們開(kāi)始變換元素。首先讓我們把鸚鵡向右移動(dòng)150單位兽掰,向下移動(dòng)200個(gè)單位芭碍。

當(dāng)然,鸚鵡是由若干路徑和形狀組成的孽尽。只要把transform屬性添加到包含它們的組上就行了窖壕;這會(huì)對(duì)整個(gè)形狀和路徑添加變換,鸚鵡會(huì)作為一個(gè)整體進(jìn)行變換杉女。查看 article on structuring and grouping SVGs獲取更多信息瞻讽。

<svg width="800" height="800" viewBox="0 0 800 600">
    <g id="parrot" transform="translate(150 200)">
        <!-- shapes and paths forming the parrot -->
    </g>
    <!-- ... -->
</svg>

下面圖片展示了上述變換后的結(jié)果。鸚鵡的半透明版本是變換前的初始位置熏挎。

svg-transformations-translate.png

SVG中的變換和HTML元素上CSS中的一樣簡(jiǎn)單直觀速勇。我們之前提到在元素上添加transform屬性時(shí)會(huì)在元素上創(chuàng)建一個(gè)新的當(dāng)前用戶坐標(biāo)系。下面圖片顯示了初始坐標(biāo)系的“副本”坎拐,它在鸚鵡元素發(fā)生變換時(shí)被建立烦磁。注意觀察鸚鵡當(dāng)前坐標(biāo)系是如何變換的。

svg-transformations-translate-system.png

這里需要注意的非常重要的一點(diǎn)是建立在元素上的新的當(dāng)前坐標(biāo)系是初始用戶坐標(biāo)系的復(fù)制哼勇,在里面元素的位置得以保持都伪。這意味著它不是建立在元素邊界盒上,或者新的當(dāng)前坐標(biāo)系的尺寸受制于元素的尺寸积担。這就是HTML和SVG坐標(biāo)系之間的區(qū)別院溺。

建立在變換元素上的新當(dāng)前坐標(biāo)系不是建立在元素邊界盒上,或者新的當(dāng)前坐標(biāo)系的尺寸受制于元素的尺寸磅轻。

The new current coordinate system established on a transformed element is not established on the element's bounding box, nor is its size restricted to the size of the element.(在轉(zhuǎn)換后的元素上建立的新當(dāng)前坐標(biāo)系不是在元素的邊框上建立的珍逸,其大小也不限于元素的大小。)

我們把小狗變換到畫(huà)布的右下方時(shí)會(huì)更加明顯聋溜。試想我們想要把小狗向右移動(dòng)50單位谆膳,向下移動(dòng)50單位。這就是狗的最初的坐標(biāo)以及新的當(dāng)前坐標(biāo)系(也因?yàn)楣犯淖儯?huì)如何顯示撮躁。注意小狗的新的坐標(biāo)系統(tǒng)的原點(diǎn)不在狗邊界盒子的左上角漱病。另外注意狗和它新的坐標(biāo)系看起來(lái)它們好像移動(dòng)到畫(huà)布新的一層上。

svg-transformations-translate-dog.png

現(xiàn)在我們?cè)囈辉嚻渌虑椤2辉僖苿?dòng)杨帽,試著縮放漓穿。我們將鸚鵡放大到兩倍尺寸:

<svg width="800" height="800" viewBox="0 0 800 600">
    <g id="parrot" transform="scale(2)">
        <!-- shapes and paths forming the parrot -->
    </g>
    <!-- ... -->
</svg>

放縮SVG元素和放縮HTML元素的結(jié)果不一樣∽⒂縮放后SVG元素的在視窗中的位置隨著縮放改變晃危。下面圖片展示了把鸚鵡放大到兩倍時(shí)的結(jié)果。注意初始位置和尺寸老客,以及最終位置和尺寸僚饭。

svg-transformations-scale-1.png

從上面圖片中我們可以注意到不只鸚鵡的尺寸(寬和高)變成了兩倍,鸚鵡的坐標(biāo)(x和y)也乘以了縮放因子(這里是兩倍)胧砰。

這個(gè)結(jié)果的原因我們之前已經(jīng)提到了:元素當(dāng)前坐標(biāo)系發(fā)生變化鳍鸵,鸚鵡在新系統(tǒng)中繪制。所以尉间,在這個(gè)例子中偿乖,當(dāng)前坐標(biāo)系被縮放。這個(gè)效果類似于使用viewBox = "0 0 400 300"哲嘲,等于“放大”了坐標(biāo)系汹想,因此把里面的內(nèi)容放大到雙倍尺寸(如果你還沒(méi)有讀過(guò)請(qǐng)查看這個(gè)系列的第一部分)。

所以撤蚊,如果我們把坐標(biāo)系變換形象化來(lái)展現(xiàn)當(dāng)前變換系統(tǒng)中的鸚鵡,我們會(huì)得到以下結(jié)果:

svg-transformations-scale-system.png

鸚鵡的新的當(dāng)前坐標(biāo)系統(tǒng)被縮放损话,同時(shí)“放大”鸚鵡侦啸。注意,在它當(dāng)前的坐標(biāo)系中丧枪,鸚鵡沒(méi)有重新定位-只有縮放坐標(biāo)系統(tǒng)才會(huì)導(dǎo)致它在視窗中重定位光涂。鸚鵡在新的縮放后的系統(tǒng)中按初始的x和y坐標(biāo)被重繪。

讓我們嘗使用不同因子在兩個(gè)方向上縮放鸚鵡拧烦。如果我們添加transform="scale(2 0.5)縮放鸚鵡忘闻,我們把寬度變?yōu)閮杀陡叨葹樵瓉?lái)的一半。效果和添加viewBox="0 0 400 1200"類似恋博。

svg-transformations-scale-2.png

注意一下鸚鵡在傾斜后的坐標(biāo)系中的位置齐佳,并且把它和初始系統(tǒng)(半透明的鸚鵡)中的位置做比較:x和y位置坐標(biāo)保持不變。

在SVG中傾斜元素也導(dǎo)致元素被“移動(dòng)”债沮,因?yàn)樗?dāng)前的坐標(biāo)系統(tǒng)被傾斜了炼吴。

試想我們使用skewX函數(shù)沿x軸給一只狗增加一個(gè)傾斜變化。我們?cè)诖怪狈较蛏习压穬A斜了25度疫衩。

<svg width="800" height="800" viewBox="0 0 800 600">
    <!-- ... -->
    <g id="dog" transform="skewX(25)">
        <!-- shapes and paths forming the dog -->
    </g>
</svg>

下列圖片展示了對(duì)小狗添加傾斜變換的結(jié)果硅蹦。

svg-transformations-skew-system.png

注意到狗的位置對(duì)比初始位置也改變了,因?yàn)樗淖鴺?biāo)系也被傾斜了。

下面的圖片展示了同樣角度的情況下使用skewY()而不是skewX傾斜狗的情況:

svg-transformations-skew-system-2.png
最后童芹,讓我們嘗試旋轉(zhuǎn)鸚鵡涮瞻。旋轉(zhuǎn)默認(rèn)的中心是當(dāng)前用戶坐標(biāo)系的左上角。新的建立在旋轉(zhuǎn)元素上的當(dāng)前系統(tǒng)也被旋轉(zhuǎn)了假褪。在下面的例子中署咽,我們將把鸚鵡旋轉(zhuǎn)45度。旋轉(zhuǎn)方向?yàn)轫槙r(shí)針嗜价。

<svg width="800" height="800" viewBox="0 0 800 600">
    <g id="parrot" transform="rotate(45)">
        <!-- shapes and paths forming the parrot -->
    </g>
    <!-- ... -->
</svg>

添加上述變換的結(jié)果如下:

svg-transformations-rotate.png

你很可能想要圍繞默認(rèn)坐標(biāo)系原點(diǎn)之外的點(diǎn)來(lái)旋轉(zhuǎn)一個(gè)元素艇抠。在transform屬性中使用rotate()函數(shù),你可以聲明這個(gè)點(diǎn)久锥。試想在這個(gè)例子中我們想按照它自己的中心旋轉(zhuǎn)這個(gè)鸚鵡家淤。根據(jù)鸚鵡的寬、高以及位置瑟由,我精確計(jì)算出它的中心在(150,170)絮重。這個(gè)鸚鵡可以圍著它的中心旋轉(zhuǎn)。

<svg width="800" height="800" viewBox="0 0 800 600">
    <g id="parrot" transform="rotate(45 150 170)">
        <!-- shapes and paths forming the parrot -->
    </g>
    <!-- ... -->
</svg>

在這個(gè)時(shí)候歹苦,這只鸚鵡會(huì)被旋轉(zhuǎn)并且看起來(lái)如下:

svg-transformations-rotate-center.png

我們說(shuō)變換添加在坐標(biāo)系上青伤,因此,元素最終被影響并且發(fā)生變換殴瘦。那么究竟如何改變旋轉(zhuǎn)中心工作在坐標(biāo)系的原點(diǎn)(0狠角,0)的點(diǎn)呢?

當(dāng)你改變中心或者旋轉(zhuǎn)時(shí)蚪腋,坐標(biāo)系被變換或者旋轉(zhuǎn)特定角度丰歌,然后再次根據(jù)聲明的旋轉(zhuǎn)中心產(chǎn)生特定變換。在這個(gè)例子中:

<gid="parrot"transform="rotate(45 150 170)">

被瀏覽器當(dāng)成一系列的移動(dòng)和旋轉(zhuǎn)等同于:

<gid="parrot"transform="translate(150 170) rotate(45) translate(-150 -170)">

當(dāng)前坐標(biāo)系變換到你想要的中心店屉凯。然后旋轉(zhuǎn)聲明的角度立帖。最終系統(tǒng)被負(fù)值變換。上述添加到系統(tǒng)的變換如下:

svg-transformations-rotate-center-system.png

在我們進(jìn)行下一部分討論嵌套和組合變換前悠砚,我想請(qǐng)大家注意建立在變換元素上的當(dāng)前用戶坐標(biāo)系是獨(dú)立于建立在其他變換元素之上的其他坐標(biāo)系的晓勇。下列圖片展示了建立在狗和鸚鵡上的兩個(gè)坐標(biāo)系,以及它們之間是如何保持獨(dú)立的灌旧。

svg-transformations-multiple.png

另外注意每個(gè)當(dāng)前坐標(biāo)系仍然處于在外層容器中使用viewBox屬性建立的畫(huà)布的主要坐標(biāo)系中绑咱。任何添加到viewBox上的變換會(huì)影響整個(gè)畫(huà)布以及所有里面的元素,不管它們是否建立了自己的坐標(biāo)系枢泰。

例如羡玛,以下是把整個(gè)畫(huà)布的用戶空間從viewBox="0 0 800 600"改成 viewBox="0 0 600 450"的結(jié)果。整個(gè)畫(huà)布被縮放宗苍,保持任何添加到獨(dú)立元素上的變換稼稿。

svg-transformations-multiple-2.png

嵌套和組合變換

很多時(shí)候你可能想要在一個(gè)元素上添加多個(gè)變換薄榛。添加多個(gè)變換意味著“組合”變換。

當(dāng)變換組合時(shí)让歼,最重要的是意識(shí)到敞恋,和HTML元素變換一樣,當(dāng)這個(gè)系統(tǒng)發(fā)生了之前的變換后在添加下一個(gè)變換到坐標(biāo)系中谋右。

例如硬猫,如果你要在一個(gè)元素上添加旋轉(zhuǎn),接下來(lái)移動(dòng)改执,移動(dòng)變換會(huì)根據(jù)新的坐標(biāo)系統(tǒng)啸蜜,而不是初始的沒(méi)有旋轉(zhuǎn)時(shí)的系統(tǒng)。

下面了例子就是做了這件事辈挂。我們先添加旋轉(zhuǎn)衬横,然后沿x軸使用transform="rotate(45 150 170) translate(200)"把鸚鵡移動(dòng)200個(gè)單位。

svg-transformations-rotate-translate.png

取決于最終的位置和變換终蒂,你可以根據(jù)需要組合變換蜂林。總是記住坐標(biāo)系拇泣。

注意當(dāng)你傾斜一個(gè)元素-以及它的坐標(biāo)系統(tǒng)-坐標(biāo)系統(tǒng)不再是最初的那個(gè)噪叙,坐標(biāo)系不再會(huì)按照最初的來(lái)計(jì)算-它將會(huì)是傾斜后的坐標(biāo)系。簡(jiǎn)單來(lái)說(shuō)霉翔,這意味著坐標(biāo)系原點(diǎn)不再是90度的角睁蕾,新的坐標(biāo)會(huì)根據(jù)新的角度來(lái)計(jì)算。

當(dāng)變換元素的子元素也需要變換時(shí)會(huì)發(fā)生變換嵌套债朵。添加到子元素上的變換會(huì)累積父元素上添加的變換和它本身的變換子眶。

[對(duì)于嵌套轉(zhuǎn)換,]應(yīng)用于子元素的轉(zhuǎn)換將是應(yīng)用于其祖先元素和應(yīng)用于其祖先元素的轉(zhuǎn)換的累加葱弟。

所以,效果上來(lái)說(shuō)猜丹,嵌套變化類似于組合:唯一區(qū)別是不像在一個(gè)元素上添加一系列的變化芝加,它自動(dòng)從父元素上獲得變換,最后執(zhí)行添加在它自身的變換射窒,就像我們?cè)谏厦嫣砑拥淖儞Q一樣-一個(gè)接一個(gè)藏杖。

這對(duì)于你想要根據(jù)另外一個(gè)元素變換一個(gè)元素時(shí)尤其有用。例如脉顿,試想你想要給小狗的尾巴設(shè)定一個(gè)動(dòng)畫(huà)蝌麸。這個(gè)尾巴是#dog組的后代。

<svg width="800" height="800" viewBox="0 0 800 600">
    <!-- ... -->
    <g id="dog" transform="translate(..)">
        <!-- shapes and paths forming the dog -->
        <g id="head">
            <!-- .. -->
        </g>
        <g id="body" transform="rotate(.. .. ..)">
            <path id="tail" d="..." transform="rotate(..)">
                <!-- animateTransform here -->
            </path>
            <g id="legs">
                <!-- ... -->
            </g>
        </g>
    </g>
</svg>

試想我們變換dog組艾疟;圍繞某一點(diǎn)把它的身體旋轉(zhuǎn)一定角度来吩,然后我們想要再把尾巴旋轉(zhuǎn)一定角度敢辩。

當(dāng)尾巴被旋轉(zhuǎn)后,它從祖先(#body)身上“繼承”了變換坐標(biāo)系弟疆,也從祖先(#dog)身上繼承了變換坐標(biāo)系戚长,然后旋轉(zhuǎn)(和#body組一樣的旋轉(zhuǎn))然后在發(fā)生自身的旋轉(zhuǎn)。這里添加的一系列變換的效果類似于我們之前在上述組合變換例子中解釋的怠苔。

所以同廉,你看,在#tail上嵌套變換實(shí)際上和組合變換有一樣的效果柑司。

使用CSS屬性變換SVGs

在SVG2中迫肖,transform屬性簡(jiǎn)稱transform屬性;因?yàn)镾VG變換已經(jīng)被引入CSS3變換規(guī)范中攒驰。后者結(jié)合了SVG變化蟆湖,CSS2 2D變換和CSS 3D變換規(guī)范,并且把類似transform-origin 和 3D transformations引入了SVG讼育。

聲明在CSS變換規(guī)范中的CSS變換屬性可以被添加到SVG元素上帐姻。然而,transform屬性函數(shù)值需要遵循CSS規(guī)范中的語(yǔ)法聲明:函數(shù)參數(shù)必須逗號(hào)隔開(kāi)-空格隔開(kāi)是不允許的奶段,但是你可以在逗號(hào)前后引用一兩個(gè)空格饥瓷;rotate()函數(shù)不接受<cx>和<cy>值-旋轉(zhuǎn)中心使用transform-origin屬性聲明。另外痹籍,CSS變換函數(shù)接受角度和坐標(biāo)單位呢铆,例如角度的rad(radians)和坐標(biāo)的px,em等。

使用CSS來(lái)旋轉(zhuǎn)一個(gè)SVG元素看起來(lái)如下:

#parrot {
    transform-origin: 50% 50%; /* center of rotation is set to the center of the element */
    transform: rotate(45deg);
}

SVG元素也可以使用CSS 3D變換在三維空間中變換蹲缠。依然要注意坐標(biāo)系棺克,然而,不同于建立在HTML元素上的坐標(biāo)系线定。這意味著3D旋轉(zhuǎn)看起來(lái)也不同除非改變旋轉(zhuǎn)中心娜谊。

#SVGel {
    transform: perspective(800px) rotate3d(1, 1, 0, 45deg);
}

因?yàn)橥ㄟ^(guò)CSS來(lái)變換SVG元素非常類似于通過(guò)CSS來(lái)變換HTML元素,-語(yǔ)法層面-在這篇文章中我將跳過(guò)這個(gè)部分。

另外斤讥,在寫(xiě)這篇文章的時(shí)候纱皆,在一些瀏覽器中實(shí)現(xiàn)一些特性是不可能的。因?yàn)闉g覽器支持改變很快芭商,我建議你實(shí)驗(yàn)一下這些屬性來(lái)決定哪些可以工作哪些不可以派草,決定什么現(xiàn)在可以用什么不可以。

注意一旦CSS變換可以完全實(shí)現(xiàn)在SVG上铛楣,我依然建議你使用CSS變換函數(shù)語(yǔ)法即使你用transform屬性的形式添加變換近迁。也就是說(shuō),上面提到的transform屬性函數(shù)的語(yǔ)法還是有效的簸州。

動(dòng)畫(huà)transform

SVG變換可以變成動(dòng)畫(huà)鉴竭,就像CSS變換一樣歧譬。如果你使用CSS transform屬性來(lái)產(chǎn)生SVG變換,你可以像在HTML元素上創(chuàng)建CSS變換動(dòng)畫(huà)一樣使用CSS動(dòng)畫(huà)把這些變換變成動(dòng)畫(huà)拓瞪。

SVG transform屬性可以用SVG元素來(lái)做成動(dòng)畫(huà)缴罗。元素是SVG中三個(gè)用來(lái)給不同的SVG屬性設(shè)置動(dòng)畫(huà)的元素之一。

<animateTransform>元素的詳細(xì)信息超出了本文的范圍祭埂。請(qǐng)繼續(xù)關(guān)注我將撰寫(xiě)的一篇關(guān)于SVG動(dòng)畫(huà)元素(包括<animateTransform>)的文章面氓。

最后的話

學(xué)習(xí)SVGs一開(kāi)始可能非常困惑,如果對(duì)于坐標(biāo)系變換里的內(nèi)容不是很清楚蛆橡,尤其是如果你帶著CSS HTML變換的背景知識(shí)舌界,自然而然希望SVG元素和HTML元素的變換一樣。

然而泰演,一旦你意識(shí)到它們的工作方式呻拌,你能更好得控制SVG畫(huà)布,并且輕易操縱元素睦焕。

這一系列的最后部分藐握,我將討論嵌套SVGs和建立新的viewports和viewboxes。敬請(qǐng)關(guān)注垃喊!

本文根據(jù)SaraSoueidan的《Understanding SVG Coordinate Systems and Transformations (Part 2) — The transform Attribute》一文所譯猾普,整個(gè)譯文帶有我們自己的理解與思想,如果譯得不好或有不對(duì)之處還請(qǐng)同行朋友指點(diǎn)本谜。如需轉(zhuǎn)載此譯文初家,需注明英文出處http://sarasoueidan.com/blog/svg-transformations/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末乌助,一起剝皮案震驚了整個(gè)濱河市溜在,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌他托,老刑警劉巖掖肋,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異赏参,居然都是意外死亡志笼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)登刺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)籽腕,“玉大人嗡呼,你說(shuō)我怎么就攤上這事纸俭。” “怎么了南窗?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵揍很,是天一觀的道長(zhǎng)郎楼。 經(jīng)常有香客問(wèn)我,道長(zhǎng)窒悔,這世上最難降的妖魔是什么呜袁? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮简珠,結(jié)果婚禮上阶界,老公的妹妹穿的比我還像新娘。我一直安慰自己聋庵,他們只是感情好膘融,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著祭玉,像睡著了一般氧映。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上脱货,一...
    開(kāi)封第一講書(shū)人閱讀 52,262評(píng)論 1 308
  • 那天岛都,我揣著相機(jī)與錄音,去河邊找鬼振峻。 笑死臼疫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的铺韧。 我是一名探鬼主播多矮,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼哈打!你這毒婦竟也來(lái)了塔逃?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤料仗,失蹤者是張志新(化名)和其女友劉穎湾盗,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體立轧,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡格粪,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了氛改。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帐萎。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖胜卤,靈堂內(nèi)的尸體忽然破棺而出疆导,到底是詐尸還是另有隱情,我是刑警寧澤葛躏,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布澈段,位于F島的核電站悠菜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏败富。R本人自食惡果不足惜悔醋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望兽叮。 院中可真熱鬧芬骄,春花似錦、人聲如沸鹦聪。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)椎麦。三九已至宰僧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間观挎,已是汗流浹背琴儿。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嘁捷,地道東北人造成。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像雄嚣,于是被迫代替她去往敵國(guó)和親晒屎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容