流動的SVG線條

話很少說,咱先上效果圖:css

是否是很酷炫,這個效果是用SVG+CSS實現的,如今咱們就來一塊兒解構一下這個動畫的實現。html


預備知識

須要掌握的幾個SVG的幾個標籤用法

  • <path>git

    指令 參數 說明
    M x y 將畫筆移動到點(x,y)
    L x y 畫筆從當前的點繪製線段到點(x,y)
    H x 畫筆從當前的點繪製水平線段到點(x,y0)
    V y 畫筆從當前的點繪製豎直線段到點(x0,y)
    A rx ry x-axis-rotation large-arc-flag sweep-flag x y 畫筆從當前的點繪製一段圓弧到點(x,y)
    C x1 y1, x2 y2, x y 畫筆從當前的點繪製一段三次貝塞爾曲線到點(x,y)
    S x2 y2, x y 特殊版本的三次貝塞爾曲線(省略第一個控制點)
    Q x1 y1, x y 繪製二次貝塞爾曲線到點(x,y)
    T x y 特殊版本的二次貝塞爾曲線(省略控制點)
    Z 無參數 繪製閉合圖形,若是d屬性不指定Z命令,則繪製線段,而不是封閉圖形。

    path的指令一共有9種,但實現咱們的動畫咱們只運用了其中兩個:A和Z,因此咱們這裏着重討論一下A指令!github

    繪製圓弧指令:A rx ry x-axis-rotation large-arc-flag sweep-flag x ybash

    對於給定兩個點(一個起點一個終點)和一個半徑,能夠畫4條弧線。這四條弧線能夠按照兩種分法:svg

    1. 按角度分
      • 大於180°的
      • 小於180°的
    2. 按畫筆方向分
      • 順時針方向
      • 逆時針方向

  • rx,ry 是弧的半長軸、半短軸長度學習

  • x-axis-rotation 是圓弧旋轉角度,是此段弧所在的半長軸與水平方向的夾角。正數表明順時針轉動的角度。動畫

  • large-arc-flag 爲1 表示大角度弧線,0 表明小角度弧線。ui

  • sweep-flag 爲1表明從起點到終點弧線繞中心順時針方向,0 表明逆時針方向。url

  • x,y 是弧終端座標。

  • <defs>

    SVG 容許咱們定義之後須要重複使用的圖形元素。 建議把全部須要再次使用的引用元素定義在defs元素裏面。這樣作能夠增長SVG內容的易讀性和可訪問性。 在defs元素中定義的圖形元素不會直接呈現。 你能夠在你的視口的任意地方利用 ``元素呈現這些元素。——MDN

    這個標籤的用意簡單地說就是定義一個繪圖模板,以供咱們能夠在別處直接使用。

    在這裏咱們能夠定義咱們的漸變元素:linearGradient。

  • <linearGradient>

    linearGradient元素用來定義線性漸變,用於圖形元素的填充或描邊。——MDN

    一個漸變上的顏色坡度,是用stop元素定義的。

    例如:

    <stop offset="5%" stop-color="#F60" />
    複製代碼

    這行代碼的意思是:在距離起點位置偏移5%的地方顏色爲 #F60。

    咱們在引用本身定義的漸變進行填充顏色設置或畫筆顏色設置時,僅須要用 url()的方式鏈入漸變的ID便可,具體以下:

    stroke="url(#linear)"
    複製代碼

    這裏咱們將畫筆的顏色設置爲了ID爲linear的漸變。

還有兩個屬性:

  • stroke-dasharray

    用於建立虛線:

    stroke-dasharray = '10'
    stroke-dasharray = '10, 10'
    stroke-dasharray = '10, 10, 5, 5'
    複製代碼

繪製虛線: 一個參數時: 表示一段虛線長度和每段虛線之間的間距

兩個參數或者多個參數時:一個表示長度,一個表示間距

  • stroke-dashoffset

    stroke-dashoffset 屬性指定了dash模式到路徑開始的距離

    若是使用了一個 百分比值, 那麼這個值就表明了當前viewport的一個百分比。

    值能夠取爲負值。——MDN

    簡單的講,stroke-dashoffset設置的是畫筆起點的偏移量,正值向左偏移。

具體實現

畫SVG路徑

筆者經過描點,將網上下載下來的一張蘋果圖描出了SVG,可能不大精確,可是應該夠用。這裏放一下我描點的圖:

<path
  stroke-linecap="round"
  fill="none"
  stroke-width="10"
  stroke="url(#linear)"
  d=" M 197,148 A 87,87,0,0,0,79,214 A 282,282,0,0,0,148,438 A 54,54,0,0,0,212,448 A 87,87,0,0,1,288,448 A 54,54,0,0,0,352,438 A 282,282,0,0,0,407,350 A 87,87,0,0,1,413,189 A 87,87,0,0,0,303,148 A 141,141,0,0,1,197,148 Z "
/>
<path
  stroke-linecap="round"
  fill="none"
  stroke="url(#linear)"
  stroke-width="10"
  d=" M 237,141 A 87,87,0,0,0,314,64 A 87,87,0,0,0,237,141 Z "
/>
複製代碼

而且我將個人畫筆顏色設置爲即將編寫的漸變id。

定義漸變色

<defs>
  <linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="100%">
    <stop offset="0%" stop-color="rgb(98, 180, 76)" />
    <stop offset="20%" stop-color="rgb(242, 179, 61)" />
    <stop offset="40%" stop-color="rgb(238, 125, 55)" />
    <stop offset="60%" stop-color="rgb(205, 58, 71)" />
    <stop offset="80%" stop-color="rgb(142, 61, 140)" />
    <stop offset="100%" stop-color="rgb(39, 155, 213)" />
  </linearGradient>
</defs>
複製代碼

爲了顯示爲彩色,我設置了六個漸變顏色節點。

值得注意的是:漸變顏色的即使應用在畫筆上,他的填色仍是按照面的顏色填充來填充的。就拿這個例子來講,我在linearGradient上定義了x1="0%" y1="0%" x2="100%" y2="100%",使頁面從左上角到右下角顏色顯示爲漸變,而不是路徑的起點到終點的漸變,因此咱們定義漸變在0%和100%的顏色並不須要同樣。(實際上咱們也不能定義從路徑的起點到終點的漸變)

JavaScript獲取路徑長度

let pathLength = document.querySelectorAll('path');
pathLength.forEach((item, index) => {
  let itemLength = Math.ceil(item.getTotalLength());
  console.log(itemLength);
});
複製代碼

這裏咱們運用到了一個JavaScript API:getTotalLength(),用於獲取路徑長度,方便咱們設置偏移量。

設置動畫

path {
  animation: dash 5s linear forwards;
}
path:nth-child(2) {
  stroke-dasharray: 1162;
  stroke-dashoffset: -1162;
}
path:nth-child(3){
  stroke-dasharray: 236;
  stroke-dashoffset: -236;
}
@keyframes dash {
  to {
    stroke-dashoffset: 0;
  }
}
複製代碼

咱們的動畫使從無到有的一個過程,因此咱們將虛線長度和每段虛線之間的間距*都設置爲路徑的長度。

在這種狀況下咱們顯示的應該是完整的蘋果logo。

當咱們設置stroke-dashoffset爲路徑長度的時候,那麼咱們就將畫面的虛線部分徹底隱藏在了畫筆起點以前。整個畫面將是空空如也!

這時候咱們爲兩個path添加動畫,讓其在5s以內勻速的改變stroke-dashoffset至0,那麼呈如今咱們眼前的就是如前面的動圖所示,一個動態繪製logo的過程。

相似動畫的其餘實現

先上效果圖:

實現代碼以下:

<svg xmlns="http://www.w3.org/2000/svg" width="200px" height="164.50px" class="icon" version="1.1" viewBox="0 0 1245 1024" id="logo-pic" >
<defs>
  <linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0%" stop-color="#05a" />
    <stop offset="100%" stop-color="#0a5" />
  </linearGradient>
</defs>
<path fill="url(#linear)" d="M870.953514 333.768649c-209.781622 0-374.867027 145.020541-374.867028 322.836756s165.223784 322.836757 374.867028 322.836757a548.116757 548.116757 0 0 0 132.289729-22.417297L1124.185946 1024l-33.210811-110.702703C1179.537297 845.768649 1245.405405 756.92973 1245.405405 656.605405c0-177.816216-176.294054-322.836757-374.451891-322.836756z m-121.496217 267.208648A47.463784 47.463784 0 0 1 705.72973 556.419459 47.740541 47.740541 0 0 1 749.457297 512c33.349189 0 55.351351 22.278919 55.351352 44.557838s-22.002162 44.419459-55.351352 44.419459z m242.438919 0a47.325405 47.325405 0 0 1-43.727567-44.557838A47.602162 47.602162 0 0 1 991.896216 512c33.072432 0 55.351351 22.278919 55.351352 44.557838s-22.278919 44.419459-55.351352 44.419459z" />
<path fill="url(#linear)" d="M440.735135 0C198.434595 0 0 166.054054 0 378.326486c0 122.188108 66.006486 222.512432 176.432432 300.41946l-44.142702 133.811892 154.153513-77.907027c55.351351 10.931892 99.355676 22.278919 154.430271 22.278919 13.837838 0 27.675676 0 41.513513-1.798919a334.045405 334.045405 0 0 1-13.837838-93.267027c0-193.72973 166.054054-352.034595 374.728649-352.034595a378.88 378.88 0 0 1 42.482162 2.629189C847.429189 133.12 657.574054 0 440.735135 0zM294.192432 296.683243a53.137297 53.137297 0 1 1 52.722163-53.137297 52.860541 52.860541 0 0 1-52.722163 53.137297z m314.395676 0a53.137297 53.137297 0 1 1 52.722162-53.137297A52.860541 52.860541 0 0 1 608.864865 296.683243z" />
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="2rem" id="logo-name" >
<text text-anchor="middle" x="50%" y="50%" class="logo logo-name-text-1" >
  WeChat
</text>
<text text-anchor="middle" x="50%" y="50%" class="logo logo-name-text-2" >
  WeChat
</text>
<text text-anchor="middle" x="50%" y="50%" class="logo logo-name-text-3" >
  WeChat
</text>
</svg>
複製代碼

值得注意的是,在SVG中文字也能夠將邊框和填充分開來填色。因此這裏咱們將文字的邊框設爲最開始定義的漸變色,而填充設置爲none。

#logo-pic {
  width: 75px;
  height: 75px;
}
.logo {
  font-size: 1.25rem;
  font-weight: bold;
  fill: none;
  stroke-width: 1px;
  stroke-dasharray: 30% 70%;
  animation: stroke 4.5s infinite linear;
}
.logo-name-text-1 {
  stroke: rgb(0, 169, 86);
}
.logo-name-text-2 {
  stroke: rgb(0, 127, 129);
  animation-delay: -1.5s;
}
.logo-name-text-3 {
  stroke: rgb(0, 86, 168);
  animation-delay: -3s;
}
@keyframes stroke {
  to {
    stroke-dashoffset: -100%;
  }
}
複製代碼

筆者專門在 github 上建立了一個倉庫,用於記錄平時學習全棧開發中的技巧、難點、易錯點,歡迎你們點擊下方連接瀏覽。若是以爲還不錯,就請給個小星星吧!👍


2019/04/02

AJie

相關文章
相關標籤/搜索