canvas 和 webGL 這兩項圖形技術結合 css3 可以說能完成絕大部分的動畫和需求。但 canvas 和 webGL 畢竟是偏向底層的繪製引擎,某些場景使用起來還是過於繁瑣的,不分場合一律使用錘子解決的行為不值得提倡。svg 在解決排版,圖標,相關動畫還是非常高效的,而且 svg 還是矢量 ...
canvas 和 webGL 這兩項圖形技術結合 css3 可以說能完成絕大部分的動畫和需求。但 canvas 和 webGL 畢竟是偏向底層的繪製引擎,某些場景使用起來還是過於繁瑣的,不分場合一律使用錘子解決的行為不值得提倡。svg 在解決排版,圖標,相關動畫還是非常高效的,而且 svg 還是矢量圖形,高清還原各種屏幕尺寸的設計簡直就是神器。
svg 基礎知識不再講解,結合svg特點和應用場景,主要介紹如下幾方面的內容
- svg sprite
- css background-image 插入svg
- 文字路徑
- 路徑動畫
SVG sprite
SVG sprite 之於 font-face 的優勢就是矢量圖的抗鋸齒效果,再也不需要為適配高清屏而操心。使用方式就是 svg 標簽結合 symbol元素即可,其中 svg 是容器,而symbol 則是組件模板。怎麼把svg組件顯示出來呢?使用 use 元素指向組件的id即可,如下所示:
<svg>
<symbol id="ok">
<!-- svg元素或組合 -->
</symbol>
<!-- ... -->
</svg>
<use href="#ok"/>
當然網上有很多工具可以幫我們把圖標自動sprite,比如:iconfot,gulp-svg-symbols
在css中插入svg
SVG 添加到網頁中有多種方法,最常見的是:
- 在 HTML 中內聯
object
、iframe
或embed
標簽插入img
標簽- CSS
background-image
屬性
html 內聯方式
<svg>
<title>line</title>
<line x1="20" y1="20" x2="100" y2="100">
</svg>
使用 object、iframe 或 embed 標簽插入
<object data="flag.svg" type="image/svg+xml"></object>
<iframe src="flag.svg" frameborder="0"></iframe>
<embed src="flag.svg" type="" />
使用img標簽插入
<img src="flag.svg"/>
現在重點介紹一下使用 css background屬性插入的方式;既可以使用圖片路徑也可以使用 base64 格式的data URI 方式
.svg-bg {
background-image: url("./bg.svg");
}
.svg-background {
background-image: url("data:image/svg+xml;<DATA>");
}
我認為使用 background base64 引入svg是最具靈活性的一種方式,還可以加入svg動畫,不需要額外載入圖標,只需引入css即可。同時跟普通圖片相比它又有著抗鋸齒的優勢,因此元素尺寸隨意調整不擔心失真。比如下麵使用background data URI 引入的載入動畫css:
<style>
.loading{
width: 50px;
height: 50px;
background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Cpath d='M10 40a30 30 0 1130 30' stroke-width='4' stroke='hsl(220,90%,60%)' fill='none'%3E%3CanimateTransform attributeName='transform' begin='0s' dur='1.4s' type='rotate' from='0 40 40' to='360 40 40' repeatCount='indefinite'/%3E%3C/path%3E%3C/svg%3E")
no-repeat center / cover;
}
</style>
<body>
<div class="loading"></div>
</body>
文字路徑
svg 除了繪製圖形,插入文字也是很方便的,方式也簡單,使用 text 元素包裹文本內容即可
<text fill="hsla(260,80%,50%,1)" x="10" y="40" font-size="30"> I Love SVG </text>
還有一種很實用的效果就是文字路徑,也就是文字按照定義好的 path 進行排列顯示,這需要使用到另一個標簽 textPath。實現方式:首先定義一個path元素(這裡使用三次貝塞爾曲線),然後 textPath元素使用 xlink:href 屬性引入path,最後再用 text標簽包裹。
<g>
<title> 文字路徑 </title>
<path id="path" d="M 10 100 C 100 0 150 300 250 100" fill="none" stroke="#555"/>
<text x="10" y="100" stroke="hsl(280,100%,50%)">
<textPath xlink:href="#path">I Love SVG I Love SVG I Love SVG</textPath>
</text>
</g>
svg路徑動畫
svg動畫既可以使用 css3 相關屬性實現,也可以使用自己獨有的api實現。svg方式主要用以下標簽:
-
animate:基礎動畫元素,實現單屬性的動畫過渡效果
-
animateTransform: 實現transform變換動畫效果
-
animateMotion:路徑動畫效果
這裡只介紹路徑動畫,基礎動畫和變換動畫與css動畫相似,就不再介紹。來看一個基於 css3 的 animation 實現百分比載入的動畫。這裡用到了兩個關鍵屬性:
-
stroke-dasharray:設置線條斷開為虛線,數值越大,線就越長
-
stroke-dashoffset:設置線條的偏移,設置後,線段就會偏移相應的值,實現線條動畫只要動態改變這個偏移值就好
首先需要通過js獲取路徑的總長度
//獲取路徑長度
const arc = document.getElementById('circle');
console.log(arc.getTotalLength()); //250.92141723632812
接著編寫svg相關
<style>
circle {
fill: transparent;
stroke-width: 10px;
}
#circle {
stroke-dasharray: 250.921;
stroke-dashoffset: 250.921;
animation: round 3s linear infinite;
}
@keyframes round {
to {
stroke-dashoffset: 0;
}
}
</style>
<g>
<circle cx="100" cy="60" r="40" stroke="#ccc" />
<circle id="circle" cx="100" cy="60" r="40" stroke="hsl(160,80%,50%)" />
</g>
當然其他stroke線條動畫也類似
接著我們再基於svg animateMotion標簽來實現path路徑動畫,其中path是運動路徑,dur 是持續時間,repeatCount設置是否迴圈
<g id="pathAnimate">
<title> 路徑動畫 </title>
<path stroke="hsl(0,0%,60%)" d="M 10 300 Q 150 100 300 300 T 490 300Z" stroke-width="2" fill="none"/>
<circle cx="0" cy="0" r="8" stroke-width="1" stroke="hsl(300,10%,40%)" fill="hsl(300,100%,50%)">
<animateMotion path="M 10 300 Q 150 100 300 300 T 500 300Z" dur="4s" repeatCount="indefinite"/>
</circle>
</g>
使用svg實現路徑動畫真是性價比超高。