SVG animateMotion路徑動畫

admin發表於2017-11-25
SVG提供的動畫元素主要有如下幾個:

(1).<set>:指定的時間之後執行指定的動畫,參閱SVG animation動畫詳解一章節。

(2).<animate>:基礎動畫元素,實現單屬性的動畫效果,參閱SVG animation動畫詳解一章節。

(3).<animateTransform>:實現transform變換動畫效果,參閱SVG animateTransform變換動畫一章節。

(4).<animateMotion>:實現路徑動畫效果。

本章節將通過程式碼例項詳細介紹一下<animateMotion>元素的用法。

<animateMotion>可以讓指定的圖形元素沿著一條計算後所得路徑進行運動。

首先看一段程式碼例項:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path transform=""
        d="M0,0 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 path="M0,0 Q50,60 80,140 T340,100"
                 dur="10s"
                 begin="click"
                 fill="freeze">
  </animateMotion> 
  <g id="ant">
    <circle
          fill="red"
          fill-opacity="0.5"
          cx="0" cy="0"
          r="20"/>
    <circle
          fill="green"
          cx="0" cy="0"
          r="3"/>
  </g>
</svg>          
</body>
</html>

說明:動畫元素具有大量重複屬性,重複的不做介紹,參閱SVG animation動畫詳解一章節。

path屬性:

此屬性用來規定元素運動的路徑,語法與<path>元素的d屬性基本一致。

具體可以參閱SVG <path>路徑元素一章節。

<animateMotion>的path屬性規定的路徑並不會顯示,程式碼中紅色路徑是一個輔助線,便於觀察效果。

深入介紹:

第一段程式碼中,圓的初始位置在左上角,被遮擋了部分割槽域,有點不便於觀察。

所以我們把路徑的起點,和圓心位置都修改一下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path transform=""
        d="M20,20 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 path="M20,20 Q50,60 80,140 T340,100"
                 dur="10s"
                 begin="click"
                 fill="freeze">
  </animateMotion> 
  <g id="ant">
    <circle
          fill="red"
          fill-opacity="0.5"
          cx="20" cy="20"
          r="20"/>
    <circle
          fill="green"
          cx="20" cy="20"
          r="3"/>
  </g>
</svg>          
</body>
</html>

程式碼執行不符合預期,雖然初始狀態圓心位於路徑的初始點,但是執行開始之後並沒有沿著路徑。

路徑本質是一連串座標點的連線;被引用的元素(也就是沿著路徑運動的元素)實際運動路徑的座標是在元素初始座標基礎上,通過路徑座標對其進行translate()轉換,例如元素的初始座標是(10,10),路徑對應當前點的座標是(100,50),那麼就進行如下轉換:

[XML] 純文字檢視 複製程式碼
transform="translate(10 10) translate(100 50)"

關於transform變化可以參閱以下兩篇文章:

(1).SVG transform用法詳解一章節。

(2).SVG transform變換深入理解一章節。

下面通過程式碼例項驗證一下對實際運動路徑生成理論的論斷:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path transform=""
        d="M20,20 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 path="M20,20 Q50,60 80,140 T340,100"
                 dur="10s"
                 begin="click"
                 fill="freeze">
  </animateMotion> 
  <g id="ant">
    <circle
          fill="red"
          fill-opacity="0.5"
          cx="0" cy="0"
          r="20"/>
    <circle
          fill="green"
          cx="0" cy="0"
          r="3"/>
  </g>
</svg>          
</body>
</html>

我們將圓心座標設定為(0,0),那麼<animateMotion>元素path屬性規定的路徑座標無論如何對被引用的元素進行translate()變換,運動的路徑座標都會落在<animateMotion>元素path屬性規定的路徑之上。

特別說明:路徑動畫開始後會有一個跳躍,這是因為元素的初始座標在(0,0)位置,當開始動畫,<animateMotion>元素path屬性規定的路徑座標馬上會對元素進行translate()變換。

<mpath>元素:

上面的程式碼都是通過<animateMotion>元素path屬性來規定路徑,其實我們可以在<animateMotion>元素中巢狀<mpath>元素來規定路徑。

程式碼例項如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
#box {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg id="box" version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path
        id="path"
        d="M20,20 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 dur="10s"
                 begin="0s"
                 fill="freeze">
    <mpath xlink:href="#path" />
  </animateMotion> 
  <g id="ant" >
    <circle
          fill="red"
          fill-opacity="0.5"
          cx="0" cy="0"
          r="20"/>
    <circle
          fill="green"
          cx="0" cy="0"
          r="3"/>
  </g>
</svg>          
</body>
</html>

使用<mpath>元素可以引用外部定義好的路徑,它的優先順序要高於path屬性定義的路徑。

如果不想讓路徑顯示,那麼將路徑巢狀在<defs>元素中即可。

rotate屬性:

先來看一段程式碼例項:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path transform=""
        d="M20,20 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 path="M20,20 Q50,60 80,140 T340,100"
                 dur="10s"
                 begin="0s"
                 fill="freeze">
  </animateMotion> 
 
  <rect id="ant"
        x="0" y="0"
        width="20" height="20"
        fill="green"/>
</svg>          
</body>
</html>

上面的程式碼實現了矩形沿著路徑運動的效果,但是有點不符合實際情況,矩形的方向是固定不變的。

程式碼修改如下:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path transform=""
        d="M20,20 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 path="M20,20 Q50,60 80,140 T340,100"
                 dur="10s"
                 begin="0s"
                 rotate="auto"
                 fill="freeze">
  </animateMotion> 
 
  <rect id="ant"
        x="0" y="0"
        width="20" height="20"
        fill="green"/>
</svg>          
</body>
</html>

為<animateMotion>新增rotate="auto"之後,矩形的路徑運動就比較符合實際情況了。

auto屬性值可以規定元素自動根據運動路徑的角度(路徑曲線的切線方向)來改變它的運動方向

再來看一段程式碼例項:

[HTML] 純文字檢視 複製程式碼執行程式碼
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="author" content="http://www.softwhy.com/" />
<title>螞蟻部落</title>
<style>
* {
  margin: 0px;
  padding: 0px;
}
svg {
  border:1px solid blue;
  width:400px;
  height:300px;
  margin:200px;
}
</style>
</head>
<body>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  <path transform=""
        d="M20,20 Q50,60 80,140 T340,100"
        stroke="red"
        stroke-width="6"
        fill="none" />
  <animateMotion
                 xlink:href="#ant"
                 path="M20,20 Q50,60 80,140 T340,100"
                 dur="10s"
                 begin="0s"
                 rotate="auto-reverse"
                 fill="freeze">
  </animateMotion> 
 
  <rect id="ant"
        x="0" y="0"
        width="20" height="20"
        fill="green"/>
</svg>          
</body>
</html>

和auto類似,不過矩形在內測切線上執行,也就是在auto的映象位置。

rotate屬性值也可以是一個具體的數字,表示旋轉的度數。

keypoints屬性:

由於篇幅原因,此屬性的用法可以參閱SVG keypoints屬性一章節。

相關文章