svg配合css3動畫
正是這個季節,是以在本教程中,我将逐漸建立一些CSS動畫,以假日為主題的SVG圖示。 Iconmelon上有一些很棒的圖示,該網站上有許多免費的矢量圖示集,可讓您盡其所能 。 我使用的圖示來自設計師Sam Jones 。 是以,為自己喝一杯蛋酒,将筆記本電腦拉到yule日志上,讓我們開始吧!
SVG和網絡
如果您對在網絡上使用SVG感興趣,則圖示是一個不錯的起點。 SVG靈活,獨立于分辨率且重量輕,是以圖示自然适合于矢量格式。 另外,就像HTML一樣,SVG可以輕松地用CSS樣式化,其中包括CSS3動畫。 在圖示中添加一些與動畫的互動性,可以為使用者帶來愉悅的體驗,還可以添加有關圖示代表的内容。
有關SVG和Web的介紹,請檢視SVG檔案:從Illustrator到Web 。
注意:在撰寫本文時,以下示範使用了尖端技術,在某些浏覽器(例如Internet Explorer)中,尚不支援這些技術。 如果您按照本教程進行操作,則最好使用Chrome或Safari。 使用适當的屬性字首完全可以實作Mozilla支援。 您當然可以期望将來對這些技術的支援會有所改善。
另外:在本文中,為了簡潔和易讀,我從一些CSS屬性中省略了一些必要的浏覽器字首。 如果您想輕松編寫無字首CSS,請檢視Lea Verou的無字首庫。 您也可以嘗試在Codepen上建立示範,可以輕松配置為使用prefixfree。
準備要編輯的SVG代碼
SVG的最大問題之一就是代碼難以處理。 乍一看,我選擇的矢量圖形編輯器Illustrator導出的SVG代碼非常不可讀。 在這方面, Inkscape實際上在導出SVG方面做得更好,但是我發現簡化和格式化代碼可以大大簡化代碼的閱讀和使用。
這是我将示範的第一個動畫示例的SVG代碼,一個閃爍的聖誕燈。
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="64px" height="64px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<path id="outline" d="M38.178,12.142H25.822v10.723c-1.605,2.67-2.461,6.529-2.461,11.406c0,9.473,4.748,17.587,8.637,17.587
s8.641-8.114,8.641-17.587c0-4.881-0.854-8.744-2.461-11.412V12.142z"/>
<rect id="basefill" x="29.822" y="16.142" fill="#4D4B4C" width="4.355" height="4.273"/>
<path id="lightfill" fill="#FFFFFF" d="M31.998,47.768c-1.402-0.959-4.637-6.229-4.637-13.497c0-5.775,1.271-8.566,2.207-9.855
h4.857c0.945,1.293,2.213,4.08,2.213,9.855C36.639,41.542,33.402,46.809,31.998,47.768z"/>
</svg>
此代碼是從我的矢量編輯工具Adobe Illustrator導出的。 乍看之下幾乎是不可讀的。 這是簡化的相同标記:
<svg class="svg-light"
viewBox="0 0 64 64"
xmlns="http://www.w3.org/2000/svg"
>
<path class="outline"
d="M38.178,12.142H25.823v10.723c-1.606,2.67-2.461,6.529-2.461,11.406c0,9.473,4.748,17.587,8.636,17.587c3.889,0,8.641-8.114,8.641-17.587c0-4.881-0.854-8.744-2.461-11.412V12.142z"
/>
<rect class="base"
x="29.822"
y="16.142"
width="4.355"
height="4.273"
/>
<path class="bulb"
d="M31.998,47.768c-1.402-0.959-4.637-6.229-4.637-13.497c0-5.775,1.272-8.566,2.207-9.856h4.858c0.945,1.293,2.213,4.081,2.213,9.856C36.639,41.542,33.402,46.809,31.998,47.768"
/>
</svg>
我通過删除程式預設輸出的許多額外标記來大大簡化了該xml。 我的基本SVG元素包含以下内容:
- 一類:
。 我已經使用svg-light
字首輕松定位特定SVG中的元素。svg-
-
屬性。viewbox
屬性的值定義文檔的長寬比,并等于Illustrator中畫闆的大小。viewbox
-
屬性。 此屬性定義SVG的XML名稱空間,并幫助某些使用者代理了解标記。xmnls
于定義了組成圖像形狀嵌套在SVG内部的元件,如
paths
,
circles
和
rects
,我已經内嵌其開口标簽施加類。 元素的所有内聯屬性,例如其坐标,都已換行。 另外,我在SVG基本标簽下縮進了所有内部元素。
所有這些工作是有原因的。 首先,它使代碼更易于閱讀。 其次,在我選擇的代碼編輯器“ Sublime Text 3”中,我可以輕松折疊單個SVG元素或整個SVG,而類名仍有助于保留有關這些元素是什麼的上下文。
聖誕燈飾
好吧,讓我們進入節日氣氛,為閃爍的聖誕燈設定動畫! 這是我們将要實作的目标:
在CodePen上檢視 Noah Blon ( @noahblon )的筆燈
我想做的是為我在SVG中提供一類
bulb
的path元素制作動畫。
<path class="bulb"
d="M31.998,47.768c-1.402-0.959-4.637-6.229-4.637-13.497c0-5.775,1.272-8.566,2.207-9.856h4.858c0.945,1.293,2.213,4.081,2.213,9.856C36.639,41.542,33.402,46.809,31.998,47.768"
/>
使用CSS,我将給燈泡填充顔色并定義其動畫屬性。
.svg-light .bulb {
fill: hsl(204, 70%, 23%);
animation-name: glow-blue;
animation-duration: 1s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
animation-direction: alternate;
}
fill
屬性允許我們設定SVG元素的顔色。 如果可能的話,我喜歡使用HSL(色相,飽和度,亮度)來定義顔色值,因為使用起來非常直覺。 在這裡,我選擇了藍色(色調204),并将亮度值保持在23%的較低水準,這意味着我們将獲得深藍色。
我将燈泡設定為通過稱為
glow-blue
的關鍵幀動畫進行動畫處理。 動畫的持續時間為1秒。 動畫無限疊代,這意味着它将永遠運作。 動畫的時間安排在關鍵幀的開始和結束處得到緩解,進而在動畫的開始和結束點處建立了更加平滑的過渡。 最後,将動畫設定為交替,這意味着它将從頭到尾來回移動并再次來回移動。
提示:您可能知道CSS動畫規則有一種簡化的文法,但是我通常更喜歡将規則拆分開,以便在連結多個動畫時更易于了解,修改和共享。
現在,我将定義
glow-blue
關鍵幀動畫:
@keyframes glow-blue {
0% { fill: hsl(204, 80%, 23%); }
100% { fill: hsl(204, 80%, 63%); }
}
在這裡,我設定了要應用此動畫的元素的開始和結束填充顔色。 唯一改變的值是顔色的亮度(hsl中的“ l”位),這意味着燈光将從同一色調的較暗版本變亮。 這就是HSL提供的直覺文法。
因為我已經定義了動畫無限交替,是以燈光會從黑暗變為燈光,并且永不停止。 是以,它似乎會閃爍。
動畫多個燈光
好,現在讓我們引導内部的Clark W. Griswold并為整個聖誕燈設定動畫。 這就是我要建立的:
請參閱CodePen上的Noah Blon ( @noahblon )的Pen 540257e4a8b727e435c8e4033602ebb0
我建立了五種不同顔色的燈。 每盞燈都以20%的寬度包裹在div中。 這些div然後向左浮動,使它們彼此内聯。 由于我尚未将SVG設定為設定的高度或寬度并保留了viewbox屬性,是以SVG可以适應其父級的大小而不會丢失其長寬比或品質。 隻是SVG的巨大優勢之一。
<svg class="svg-light svg-light--red">
對于每個SVG,我都使用顔色字尾(例如svg-light--red)擴充了svg-light基類。 這是我用來為許多燈光設定動畫的規則的摘錄:
.svg-light .bulb {
animation-duration: 1s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
animation-direction: alternate;
}
.svg-light--red .bulb {
fill: hsl(6, 63%, 16%);
animation-name: glow-red;
animation-delay: .5s;
animation-duration: 1.25s;
}
@keyframes glow-red {
0% { fill: hsl(6, 63%, 16%); }
100% { fill: hsl(6, 63%, 56%); }
}
基本的動畫屬性仍将應用于
svg-light
的基類,以便可以在所有燈光之間共享它們。 對于每種顔色變化,我建立了一個不同的關鍵幀動畫(例如,
glow-red
或
glow-blue
并為它們賦予了不同的動畫延遲和持續時間。 這樣,訓示燈将以适當的顔色閃爍,并且所有訓示燈不會同時閃爍。
紅鼻子馴鹿魯道夫
我将使用與上述相同的概念來制作最著名的馴鹿魯道夫的動畫。 這是最終結果:
見筆SVG魯道夫動畫圖示使用CSS諾亞倫( @noahblon )上CodePen
首先,我将為他發光的紅鼻子設定動畫:
.svg-rudolph .nose {
animation-name: glow;
animation-duration: 6s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
animation-direction: alternate;
}
@keyframes glow {
0% { fill: hsl(6, 93%, 16%); }
50% { fill: hsl(6, 93%, 56%); }
100% { fill: hsl(6, 93%, 56%); }
}
這看起來很像我們的聖誕燈。 在關鍵幀動畫中,我設定為50%,然後設定為100%。 動畫持續時間為六秒,這意味着在三秒鐘内,鼻子将變成淺紅色,并在動畫結束前再保持該顔色三秒鐘。 另外,由于我将動畫設定為備用,是以它将從頭到尾運作。 是以,鼻子将在另外三秒鐘内保持全紅狀态,最後在最後三秒鐘内變黑。 了解關鍵幀百分比和動畫定義(例如持續時間)之間的互相作用是建立有效CSS動畫的關鍵。
我還對Rudy鼻子上的亮點應用了過渡:
.svg-rudolph .nose-highlight {
fill-opacity: 0;
animation-name: highlight-fade;
animation-duration: 6s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
animation-direction: alternate;
}
@keyframes highlight-fade {
0% { fill-opacity: 0; }
25% { fill-opacity: 0; }
100% { fill-opacity: 1; }
}
在這裡,我為另一個SVG屬性設定了動畫,即
fill-opacity
。 此屬性的取值介于0到1之間; 0為完全透明,1為完全不透明。 最後,我将讓Rudy眨眨眼,為他帶來更多的生活:
.svg-rudolph .eye {
animation-name: blink;
animation-duration: 8s;
animation-iteration-count: infinite;
transform-origin: 50%;
}
@keyframes blink {
0% { transform: scaleX(1) scaleY(1); }
1% { transform: scaleX(1.3) scaleY(0.1); }
2% { transform: scaleX(1) scaleY(1); }
60% { transform: scaleX(1) scaleY(1); }
61% { transform: scaleX(1.3) scaleY(0.1);}
62% { transform: scaleX(1) scaleY(1); }
100% { transform: scaleX(1) scaleY(1); }
}
我已經建立了一個名為
blink
的動畫。 該動畫運作八秒鐘,永不停止。 這次我不改變動畫,而是動畫将運作到最後,然後從頭開始。
在關鍵幀中,通過操縱X和Y軸上的眼睛比例來建立閃爍的動畫。 例如,在1%的标記處,眼睛在X軸上的大小縮放為1.3倍,在Y軸上的大小縮放為正常大小的0.1倍。 換句話說,它們變寬了一些,變短了一些。 在動畫持續時間的百分之一之後,眼睛的大小恢複正常。 是以,規模變化發生得非常快。 8秒/ 100 = 8分之一秒。
使用transform為SVG元素設定動畫的關鍵組成部分是設定元素
transform-origin
。 在大多數情況下,為了在SVG中正确應用變換,我們必須将變換坐标的原點定義為元素的中心。 與HTML元素不同,預設情況下,SVG元素的變換原點是其左上角,即(0,0)坐标。 通過将transform-origin設定為(50%,50%),變換的X和Y軸的原點将位于元素的中心,然後可以正确應用變換。
注意: Firefox在轉換原點時遇到問題。 不幸的是,将轉換原點設定為50%實際上會重置元素的X / Y坐标。 一種解決方法是将元素轉換回其原始位置。
丁東高中
對于此示範,我将為這樣的鈴聲制作動畫:
請參閱CodePen上的Noah Blon ( @noahblon )的Pen 63cdc3e8e785028deb35132d889b6090
讓我們看一下SVG标記的摘錄:
<svg class="svg-bell" viewBox="0 0 88 72" xmlns="http://www.w3.org/2000/svg">
<g class="group-striker">
<circle class="outline"
cx="43.998"
cy="54.571"
r="7.99"
/>
<circle class="fill"
cx="43.998"
cy="54.567"
r="3.99"
/>
</g>
<g class="group-bell">
<path class="outline"
d="M71.5,38.184h-3.291l-6.213-21.879c-1.367-4.816-5.951-8.693-10.904-9.514C50.91,3.02,47.812,0,43.996,0c-3.812,0-6.91,3.018-7.092,6.787c-4.957,0.822-9.539,4.697-10.908,9.514l-6.211,21.883h-3.289l-4.498,15.85h19.251H36h15.994h3.963h20.041L71.5,38.184z M40.975,6.611C41.229,5.143,42.455,4,43.996,4c1.543,0,2.77,1.143,3.025,2.615L40.975,6.611z"
/>
<path class="fill"
d="M29.844,17.395c1.045-3.678,5.156-6.783,8.975-6.783l10.355,0.004c3.82,0,7.93,3.105,8.975,6.783l5.902,20.785H23.943L29.844,17.395z"
/>
<polygon class="fill"
points="19.52,42.184 68.477,42.184 70.705,50.033 17.291,50.033"
/>
</g>
</svg>
我已經包裝好鐘形輪廓并填充了
<g>
(或組)标簽。 此标記對于組織元素非常有用,類似于您可以使用
<div>
包裝多個HTML元素的方式。 可以将動畫應用于組。 因為在這種情況下,我希望鐘形的填充和輪廓都旋轉,是以我可以隻旋轉組而不是分别旋轉每個元素。
.svg-bell .group-bell {
animation-name: bell-ring;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: ease-in-out;
animation-delay: -1.5s;
animation-direction: alternate;
transform-origin: 50%;
}
@keyframes bell-ring {
0% { transform: rotate(27deg); }
100% { transform: rotate(-27deg); }
}
到目前為止,這個CSS應該已經很熟悉了,但是有一些新的事情正在發生。 首先,在關鍵幀動畫中,對鐘進行了變換,但是我不是在變換比例,而是在變換元素的旋轉值。 此動畫使鈴铛在27到-27度之間擺動。
我做的另一件事是對
animation-delay
使用負值。 負值會使動畫開始該時間段進入動畫。 在這種情況下,動畫将在動畫開始1.5秒後開始,而不是在1.5秒的延遲後開始動畫。 這樣,鈴铛将從動畫開始1.5秒的空檔位置開始,而不是動畫開始0秒的空轉位置開始。
.svg-bell .striker {
animation-name: striker-move;
animation-duration: 3s;
animation-iteration-count: infinite;
animation-timing-function: linear;
animation-delay: 1.5s;
animation-direction: alternate;
transform-origin: 50%;
}
@keyframes striker-move {
0% { transform: translateX(3px); }
100% { transform: translateX(-3px); }
}
我對包含鈴铛前鋒元素的組應用了類似的動畫。 但是,這一次,我是沿X軸平移或移動元素,而不是旋轉它們,是以撞針将左右擺動。
讓它下雪吧!
對于此動畫,我将為落在雪球内部的雪設定動畫。
請參閱CodePen上的Noah Blon ( @noahblon )的Pen 2addb5f98c757d61cec87bdcacb5870d
我建立了一堆用于表示雪的圓形元素,并将這些元素放在雪球的周圍,并用
<g>
标簽包裹它們。
由于我已将剪切路徑應用于包含雪的組,是以在雪球之外看不到雪。 剪切路徑是可以應用于SVG元素的形狀,可以掩蓋其中的其他形狀。 在我們的地球儀示例中,我建立了一個圓形的剪切路徑,它覆寫了地球的内部。
<defs>
<clipPath id="globeClipPath">
<circle cx="32" cy="31" r="26.825"/>
</clipPath>
</defs>
<clipPath>
标簽是我們的masking元素,要實作它,我們必須給它一個ID。
我已經将剪切路徑包裝在
defs
标簽中。 SVG允許我們建立以後可以重用的元素,例如剪切路徑,過濾器或可以沖壓出的形狀。 最佳做法是将定義(例如剪切路徑)包裝在defs标簽中,以便可以更輕松地讀取SVG。
要應用剪切路徑,我們在SVG元素的内聯剪切路徑屬性中引用其url,在這種情況下,其ID前面是一個哈希符号:
<g class="group-snow" clip-path="url(#globeClipPath)">
<circle class="snow"
cx="49.498"
cy="8.482"
r="2.5"
/>
<circle class="snow"
cx="35.748"
y="2.783"
r="2.5"
/>
<circle class="snow"
cx="21.001"
cy="4.728"
r="2.5"
/>
<circle class="snow"
cx="28.25"
cy="2.783"
r="2.5"
/>
<circle class="snow"
cx="42.997"
cy="4.728"
r="2.5"
/>
<circle class="snow"
cx="14.502"
cy="8.482"
r="2.5"
/>
<circle class="snow"
cx="9.194"
cy="13.793"
r="2.5"
/>
<circle class="snow"
cx="54.806"
cy="13.793"
r="2.5"
/>
</g>
現在,雪隻在該圓形剪切路徑的内部可見。
使用與我之前介紹的技術相同的方法對雪進行動畫處理; 沿Y軸平移,并且随着動畫結束,填充不透明度接近零。
.svg-snowglobe .snow {
animation-name: snowfall;
animation-duration: 10s;
animation-iteration-count: infinite;
animation-timing-function: ease-in;
}
.svg-snowglobe .snow:nth-child(1) { animation-delay: 2s; }
.svg-snowglobe .snow:nth-child(2) { animation-delay: 4s; }
.svg-snowglobe .snow:nth-child(3) { animation-delay: 6s; }
.svg-snowglobe .snow:nth-child(4) { animation-delay: 8s; }
.svg-snowglobe .snow:nth-child(5) { animation-delay: 10s; }
.svg-snowglobe .snow:nth-child(6) { animation-delay: 12s; }
.svg-snowglobe .snow:nth-child(7) { animation-delay: 14s; }
.svg-snowglobe .snow:nth-child(8) { animation-delay: 16s; }
.svg-snowglobe .snow:nth-child(9) { animation-delay: 18s; }
.svg-snowglobe .snow:nth-child(10) { animation-delay: 20s; }
是的,CSS3選擇器可用于SVG元素! 在這裡,我為每個降雪元素賦予了不同的延遲,是以它們不會一次全部掉落。
季節的問候
最後,我将為基于SVG的文本設定動畫,以實作如下結果:
在CodePen上檢視 Noah Blon ( @noahblon )的筆消息
SVG使我們能夠使用CSS将筆觸應用于SVG元素。 在上一個動畫中,我将向您展示如何逐漸繪制元素的筆觸。
為了實作此動畫,我使用了以下筆觸屬性:
-
:筆劃的寬度。 這是相對于SVG的大小,是以是響應性的。stroke-width
-
:筆觸的顔色。stroke
-
:定義虛線描邊。 交替值的數組定義虛線繪制部分的長度以及虛線之間的空白區域。stroke-dasharray
-
:定義相對于路徑長度的筆畫起始位置。stroke-dashoffset
設定描邊文本需要在圖形編輯器中進行一些工作。 我的工作流程如下:
- 建立一個文本元素。
- 将該文本轉換為矢量路徑。
- 将這些路徑合并為複合路徑。
這是我設定動畫CSS:
.svg-message .text {
stroke-width: 1px;
stroke: hsl(6, 63%, 36%);
stroke-dasharray: 1865.753px 1865.753px;
stroke-dashoffset: 1865.753px ;
fill-opacity: 0;
fill: hsl(6, 63%, 36%);
animation-name: stroke, fill;
animation-duration: 1s;
animation-delay: 0, 1s;
animation-iteration-count: 1;
animation-timing-function: ease-in-out;
animation-fill-mode: forwards;
}
@keyframes fadeIn {
0% { fill-opacity: 0; }
100% { fill-opacity: 1; }
}
@keyframes drawStroke {
100% { stroke-dashoffset: 0 }
}
我已将
stroke-dasharray
屬性定義為總路徑的長度(您可以使用Object選項在Illustrator中的Document Info Palette下找到此值)。 然後,我給
stroke-dashoffset
設定了路徑總長度的值,這将整個筆劃推到可見性之外。 然後,通過關鍵幀為
stroke-dashoffset
屬性設定動畫,筆畫将逐漸在螢幕上繪制。
如果您想了解更多有關此技術的資訊,請檢視Jake Archibald的SVG中的Animated線描 。
我還設定了線條繪制完成後使用淡入淡出的屬性來填充文本,該屬性類似于我之前對snowglobe動畫所做的操作。
借助SVG和CSS進一步發展
在本教程中,我已示範了使用CSS和SVG可以建立一些非常有效的動畫。 如果您想使用所有代碼以及一些其他動畫,可以從Github下載下傳示例,或在Codepen上檢視我的收藏集 。
如果您想變得更進階,可以探索用JavaScript控制CSS動畫,或者用更複雜JavaScript動畫來補充CSS動畫,例如令人驚歎的SVG JS庫Snap SVG支援的動畫。
感謝您跟随本教程的學習,我迫不及待想看到您提出的創意!
翻譯自: https://webdesign.tutsplus.com/tutorials/how-to-animate-festive-svg-icons-with-css--webdesign-17658
svg配合css3動畫