TweenLiteを使用して SVG polygon(polyline) を任意の形状へ変形アニメーションさせる方法

この記事は2年前に書かれました。不適当な記述を含む場合がありますので、参考程度に留めてください。

どうもこんばんは。Toshikuraです。久しくTipsを書いていなかったのですが地味に便利でしたので【TweenLiteを使用して SVG polygon を任意の形状へ変形(アニメーション)させる方法】をメモしておきます。今回のTipsでは TweenLite(Gsap)を使用します。
 

SVG polygon

SVGのpolygon(もしくはpolyline)はSVG内のXY座標をpoints=”X1,Y1 X2,Y2 …”と指定し、点と点と繋ぐ事で図形を描写しています。
 


<a id="onChangeByTM" href="#">HOVER</a>
<svg viewBox="0 0 158.5 183" width="200px">
<polygon id="poly" points="0,45.8 79.2,0 158.5,45.8 158.5,137.3 79.2,183 0,137.3"/>
</svg>

 

開始時と終了時の指定

まず points=”X1,Y1 X2,Y2 …” を[X1,Y1,X2,Y2…]のようにArrayとして扱います。変形に際しては開始時の図形を[X1,Y1,X2,Y2…]とし終了時の図形を[X’1,Y’1,X’2,Y’2…]とします。デモでは以下のような数値としています。
 


//現在
var svgOrigin = [0,45.8,79.2,0,158.5,45.8…];
//開始時
var svgFromOrigin = [0,45.8,79.2,0,158.5,45.8…];
//終了時
var svgToOrigin = [79.2,43.5,79.2,43.5,129.2…];

svgFromOriginが開始時、svgToOriginが終了時の値です。svgOriginは開始時の値と同値ですがこれが現在のpolygonの形状になります。アニメーションを行う際はこのsvgOriginの値を変化させpolygonのpointsに入れ込みます。
 

TweenLite

変形に際してはTweenLiteを使用します。TweenLiteではArrayやObjectの取扱いが軽量かつ容易です(※1)。TweenLite.to(arrayA, 1, arrayB);とすることでarrayAからarrayBへ1sをもって変化(アニメーション)させる事が可能です。

※1)がりがり属性を書き換えている事に変わりはないので使い方や使いどころには注意してください。


var svgOrigin = [0,45.8,79.2,0,158.5,45.8…];
var svgFromOrigin = [0,45.8,79.2,0,158.5,45.8…];
var svgToOrigin = [79.2,43.5,79.2,43.5,129.2…];

TweenLite.to(svgOrigin, 0.5, svgToOrigin);
svgToOrigin.onUpdate = function() {
// svgOriginがsvgToOriginへアップデートされている間実行
};


 

変形

この段階ではarrayAからarrayBへの変化はTweenLiteによって行えましたが肝心のpoints属性への変換(書き換え)は行っていません。ですので新たにconvertToPoints(array)という関数を用意します。単純な関数で受け取ったarrayをpoints形式にしてpolygonへ渡すだけです。


var poly = document.getElementById(“poly”);
function convertToPoints(arr){
var svg = “”;
for (var i = 0; i < arr.length; i++) { var str = i%2 ? arr[i] + " " : arr[i] + ","; svg += str; }; poly.setAttribute("points",svg); }

 

マウスオーバー / マウスアウト

最後にマウスオーバーとマウスアウトの指定を行います。以下一通りのソースです。動きに関してはDEMOをご確認ください。
 


<a id="onChangeByTL" href="#">HOVER</a>
<svg viewBox="0 0 158.5 183" width="200px">
<polygon id="poly" points="0,45.8 79.2,0 158.5,45.8 158.5,137.3 79.2,183 0,137.3 "/>
</svg>

<script>

var svgOrigin = [0,45.8,79.2,0,158.5,45.8,158.5,137.3,79.2,183,0,137.3];
var svgFromOrigin = [0,45.8,79.2,0,158.5,45.8,158.5,137.3,79.2,183,0,137.3];
var svgToOrigin = [79.2,43.5,79.2,43.5,129.2,130.1,129.2,130.1,29.2,130.1,29.2,130.1];

var poly = document.getElementById("poly");
function convertToPoints(arr){
var svg = "";
for (var i = 0; i < arr.length; i++) {
var str = i%2 ? arr[i] + " " : arr[i] + ",";
svg += str;
};
poly.setAttribute("points",svg);
}

var btn = document.getElementById("onChangeByTL" );
btn.onmouseover = function(){
TweenLite.to(svgOrigin, 0.5, svgToOrigin);
svgToOrigin.onUpdate = function() {
convertToPoints(svgOrigin);
};
};
btn.onmouseout = function(){
TweenLite.to(svgOrigin, 0.5, svgFromOrigin);
svgFromOrigin.onUpdate = function() {
convertToPoints(svgOrigin);
};
};

</script>

DEMO Polygon
DEMO Polyline