anime.js(2):基礎的な利用

●基礎的な利用

 
anime.jsはアニメを設定した瞬間に再生されてしまいます。もし勝手に再生したくないときはautoplayオプションをfalseにしておきます。再生はplayメソッドを利用します。kute.jsと異なりオプション用の{}は無くプロパティと同じ場所に設定します。

autoplay:ボタンを押してから再生
http://jquerystudy.info/anime/0_core/00_intro.html/
var animeObj = anime({targets:'.box',left:	'500px', autoplay:false});
document.getElementById("btn_start").onclick = function (){
	animeObj.play();
}

anime.jsはイージングのデフォルトがlinearではない珍しいライブラリです。以下サンプルではlinearを設定しました。他に利用できるイージングはここを参照してください。
 
Elasticなものに関してはパラメータを設定できます(後日サンプルを作る予定)。またベジェ式を利用したカスタムイージングも作成でき、かなり高機能な印象。
→参考:Easing functions

var animeObj = anime({targets:'.box',left:'500px',easing:'linear',autoplay:false});

複数要素に対応しています(kute.jsとことなりメソッドが変わるようなことはありません)。

複数要素をまとめてアニメ
http://jquerystudy.info/anime/0_core/03_multi.html/
<div id="b1" class="box">1</div>
<div id="b2" class="box">2</div>
<div id="b3" class="box">3</div>
<div id="b4" class="box">4</div>
<div id="b5" class="box">5</div>
var animeObj = anime({targets:'.box',left:'500px',easing:'linear',autoplay:false});

 
複数のプロパティを同時にアニメできます。

var animeObj = anime({
	targets:'.box',
	top:'500px',
	left:'500px',
	rotate:'180',
	easing:'linear',
	autoplay:false
});

プロパティ毎に詳細を設定したい場合はプロパティ毎に{}を設定します。共通で参照する値は通常の位置に書きます(今回の例ではautoplayが共通)。

var animeObj = anime({
	targets:'.box',
	top:{
		value:'500px',
		easing:'linear',
		duration:500
	},
	left:{
		value:'500px',
		easing:'easeInOutSine',
		duration:1000
	},
	autoplay:false
});

targetsは個別には設定できないようなので、以下のように別々に設定しよう。

ターゲット毎に異なるアニメを設定
http://jquerystudy.info/anime/0_core/06_openDoor.html/
var leftObj = anime({targets:'#doorLeft',width:'0px'
	,easing:'linear',duration:1000,autoplay:false});
var rightObj = anime({targets:'#doorRight',width:'0px',left:'320px'
	,easing:'linear',duration:1000,autoplay:false});

ターゲットを配列で指定することができます。

ターゲットを配列で指定
http://jquerystudy.info/anime/0_core/07_array.html/
var animeObj = anime({targets:['#b1','#b3','#b5'],left:'500px',easing:'linear',autoplay:false});

DOM要素の属性値も変更できます。サンプルではinputのvalue属性を変更しています(roundは小数点の設定)。

inputタグのvalue値を操作
http://jquerystudy.info/anime/0_core/08_dom.html/
var animeObj = anime({targets:'input',value:100,round: 1,
	easing:'linear',duration:3000,autoplay:false});

属性が変更できるということは横スクロールも可能ということ。

var animeObj = anime({targets:scrollElm,scrollLeft:5000,easing:'linear',autoplay:false});

サンプルは作成しませんでしたがobjectデータの値も変更できます。
※他の項目と組み合わせてサンプルを作る予定。
→参考:JavaScript Object properties

色の指定方法は3種類(hex/rgb/hsl)ある

var color_1 = anime({targets:'#b1',backgroundColor:'#FFF',easing:'linear',autoplay:false});
var color_2 = anime({targets:'#b2',backgroundColor:'rgb(255,255,255)',easing:'linear',autoplay:false});
var color_3 = anime({targets:'#b3',backgroundColor:'hsl(0, 0%,100%)',easing:'linear',autoplay:false});

hslがあるのできれいな色環アニメができると思ったけど、少し直線的な雰囲気。

hslを利用した色環アニメ
http://jquerystudy.info/anime/0_core/11_circle.html/

 
次回に続く。
 
 
 

 
 
 

anime.js(1):イントロ

●周辺状況

公式サイトは以下。documentationページが素敵!。装飾過多なサンプルではなく要点だけのサンプルなので分かりやすい!

anime.js:公式サイト
http://animejs.com//

1101
 
日本語で説明しているサイトは以下。このライブラリもkute.js同様に最近登場したライブラリなので少し不安…。
→参考:軽量・簡単なのにいきいきしたアニメーションが付けられる!anime.jsを触ってみた
→参考:CSSライクでデザイナーに優しい!anime.jsはDOMアニメーションの新定番だ!
 
上記サイト内にあるリンクで特に以下のサイトが素敵。操作が分かりにくいですが、各項目毎に設置された「previous/next」のボタンを押す毎にテキストがアニメーションします(このサンプルが学ぶ切欠になった)。
 
→参考:Letter Effects with anime.js
1101_1
 
 

●対応ブラウザ

レガシーブラウザには対応していない。IEはver10以上。公式サイト(github)のBrowser supportを参照してください。
→参考:公式サイト(github)
 

●導入

kute.jsとことなりhead内でリンクしても機能しました。

anime({
	targets:'.box',
	left:	'500px'
});

—————————————-
・デフォルトのイージングがlinearでないのは珍しい
・デフォルトでアニメは勝手に再生される
—————————————-
なんとなく良い雰囲気を感じる。
 
アニメだけではなく数値のみを変化させることができるのが「なんとなく」素敵。公式サイトの以下に説明有り。
→参考:JavaScript Object properties
 
今日はここまで。
 
 
 

kute.js(2): コールバックとシーケンスアニメ

●callBack:コールバック

コールバックはdurationと同じoptionの{}内に設定する。completeはアニメ終了後に実行するfunctionを設定できます。

callback:アニメ後の処理を設定
http://jquerystudy.info/kute/0_core/16_cb_comp.html/
var tween = KUTE.fromTo('.box',{left:0},{left:500},
	{duration:500,complete:completeFunc});

animationFrame毎にコールするupdateの設定もあります。

callback:毎フレームごとの処理を設定
http://jquerystudy.info/kute/0_core/17_cb_update.html/
var tween = KUTE.fromTo('.box',{left:0},{left:500},
	{duration:500,update:updateFunc});

 

●chain:アニメの連結

アニメを連結するにはchainメソッドを利用すします。しかし以下ページで「chain multiple tweens」を検索して表示される機能が実現できません(私の解釈が間違っているのかな…)。
→参考:kute.js: Public Methods

chain:正常に機能しない…
http://jquerystudy.info/kute/0_core/18b_chain.html/
tween.chain(tween_2,tween_3,tween_4,tween_5);

そしてexampleのサンプルをみるとマニュアルと異なる構文で連結しています。
→参考:chain transform animations with kute.js
 
その構文を利用して連結してみた。引数に設定したtweenをオブジェクトとして次のtweenに繋いでいくのがポイント。

tween.chain(tween_2);
tween_2.chain(tween_3);
tween_3.chain(tween_4);
tween_4.chain(tween_5);

chainの別サンプル。1つの要素に対してアニメを連結した。

chain:いつの要素にシーケンシャルなアニメを
http://jquerystudy.info/kute/0_core/19_single.html/
var tween_1 = KUTE.to('.box',{left:500});
var tween_2 = KUTE.to('.box',{top :500});
var tween_3 = KUTE.to('.box',{left:0});
tween_1.chain(tween_2);
tween_2.chain(tween_3);

 

●both:アニメ連結とコールバック

chainした各アニメでコールバックが発生するか確認。アニメが切り替わる毎にdiv内の数値が変化します。この処理はjQueryよりもシンプルに記述できて嬉しい

連結したアニメ毎にコールバックを受け取る
http://jquerystudy.info/kute/0_core/20_cb_chain.html/
var tween_1 = KUTE.to('.box',{left:500},{complete:complete_1});
var tween_2 = KUTE.to('.box',{top :500},{complete:complete_2});
var tween_3 = KUTE.to('.box',{left:0  },{complete:complete_3});
tween_1.chain(tween_2);
tween_2.chain(tween_3);

 

●他のアニメライブラリを探そう…

突然ですがkute.jsの勉強は中断して、他のアニメライブラリを検討しようと思います。
ここまでの学習で躓いた箇所は3つ。
—————————————
・横スクロールに対応していない
・repeatDelayがyoyo以外で機能しない
・chain multiple tweensが機能しない
—————————————
上記に対しネットで情報収集したのですが英語サイトを含めても情報が少なく、技術系の掲示板でも議論がほとんどされていませんでした。とはいえ、新しいライブラリなので仕方ない部分なのでしょう…。 
 
もっと情報が充実してから再開しようと思います。
次回からはanime.jsを調査しようと思います。
 

●メリット

kute.jsの自習は中断となりましたがメリット的な機能をメモ。パースや基準点を変更した変形を手軽に出来るのがkute.jsのメリットだと思う。なので、それらを利用したデモがサイトトップで実演されている。とはいえ、それらはcss3の機能にもあるので他のライブラリでもできるよね?(追々調べてみよう)
→参考:MDN: perspective
→参考:MDN: perspective-origin
→参考:MDN: transform-origin
 

パースを設定したY軸回転
http://jquerystudy.info/kute/0_core/21_pers.html/
var tween = KUTE.fromTo('.box',{rotateY:0},{rotateY:180},{perspective:100});
var tween = KUTE.fromTo('.box',{rotate:0},{rotate:180},{transformOrigin:'100% 100%'});

 
おしまい
 

kute.js(1):基礎的なアニメ

●Core:基礎的な使い方

以下のサイトが参考になりました。
→参考:CSS,SVG,テキスト要素に様々なアニメーションを低負荷で施せる「KUTE.js」
 
toメソッドを利用すると指定した値にアニメします。返値はtweenオブジェクトと呼ばれる。

to:ボタンを押すと透明に
http://jquerystudy.info/kute/0_core/02_simple.html/
var tween = KUTE.to('.box',{opacity:0},{duration:1500});
document.getElementById("btn").onclick = function (){
	tween.start();
}

toメソッドは複数要素に対応していない。

to:2つめのboxは消えません…
http://jquerystudy.info/kute/0_core/03_allto.html/
<div id="testArea">
	<div id="b1" class="box">box 1</div>
	<div id="b2" class="box">box 2</div>
</div>

複数の要素をアニメさせる場合はallToメソッドを利用する

allTo:複数の要素はallToを使う
http://jquerystudy.info/kute/0_core/04_allto2.html/
var testAnime = KUTE.allTo('.box',{opacity:0},{duration:1500});
document.getElementById("btn").onclick = function (){
	testAnime.start();
}

イージングの設定(公式サイト:イージングの種類
ちなみにアニメを初期状態に戻すメソッドはない。そのため下記サンプルのresetボタンはjavaScriptで位置を設定しなおしています。

 
fromToメソッドを利用すると初期値も設定できるのでresetボタンは不要になります。

fromTo:アニメの初期値も設定する
http://jquerystudy.info/kute/0_core/06_fromTo.html/
var tween_1 = KUTE.fromTo('#b1',{left:0},{left:500},{duration:1500, easing:'linear'});

複数の要素に対応したallFromToメソッドもあります。

allFromTo:複数要素でアニメの初期値も設定する
http://jquerystudy.info/kute/0_core/07_allFromTo.html/
var tween = KUTE.allFromTo('.box',{left:0},{left:500},{duration:1500});

複数要素をずらして再生したいときはoffsetオプションが便利

offset:複数要素をずらして再生
http://jquerystudy.info/kute/0_core/08_offset.html/
var tween = KUTE.allFromTo('.box',{left:0},{left:500},{duration:500, offset:100});

個別にアニメをずらす場合はdelayオプションを使います。

var tween_1 = KUTE.fromTo('#b1',{left:0},{left:500},{duration:1500,delay:0});
var tween_2 = KUTE.fromTo('#b2',{left:0},{left:500},{duration:1500,delay:400});
var tween_3 = KUTE.fromTo('#b3',{left:0},{left:500},{duration:1500,delay:800});
var tween_4 = KUTE.fromTo('#b4',{left:0},{left:500},{duration:1500,delay:600});
var tween_5 = KUTE.fromTo('#b5',{left:0},{left:500},{duration:1500,delay:200});

繰り返しアニメさせたいときはrepeatオプションを使う。繰り返し数なので1を指定すると元のアニメと合わせて計2回となります。

var tween = KUTE.allFromTo('.box',{left:0},{left:500},{duration:500, repeat:1});

ver1.6から無限ループ(Infinity)が設定できるようになりました。

var tween = KUTE.allFromTo('.box',{left:0},{left:500},{duration:500, repeat:Infinity});

repeatDelayオプションを設定すると繰り返し間隔を設定できるはずなのに機能しない…

repeatDelay:繰り返し間隔を設定する(機能しない…)
http://jquerystudy.info/kute/0_core/12_repeat_delay.html/
var tween = KUTE.allFromTo('.box',{left:0},{left:500},
	{duration:500, repeat:10,repeatDelay:500});

yoyoオプションをtrueにすると反復繰り返しになります

var tween = KUTE.allFromTo('.box',{left:0},{left:500},
	{duration:500, repeat:Infinity, yoyo:true});

yoyoオプションをtrueにするとrepeatDelayが効くようになった…

yoyo & repeatDelay:往復の間隔を設定
http://jquerystudy.info/kute/0_core/14_yoyo_delay.html/
var tween = KUTE.allFromTo('.box',{left:0},{left:500},
	{duration:500, repeat:Infinity, yoyo:true, repeatDelay:1000});

複数プロパティのアニメさせることも可能。

multi:複数のプロパティをまとめてアニメ
http://jquerystudy.info/kute/0_core/15_multi.html/
var tween = KUTE.allFromTo('.box',{left:0, top:0, rotate:0},
	{left:500, top:500, rotate:360},{duration:500, repeat:Infinity, yoyo:true});

 

●人気がない?

なんとなくkute.jsを採用するのは危険な気がしてきた…。
———————-
前回の記事で横スクロールに対応していないと書いたが、こういう演出系のライブラリってcssやhtmlの属性/プロパティを直接操作できるものが多いので、scrollLeftとかを操作すれば横スクロールできそうなのに、それができない。
 
単一要素と複数要素で利用するメソッドが異なる(fromTo/allFromTo)。分けた方が高速に処理できるのだろうけれど、少し違和感。
 
repeatDelayってyoyoの時にしか設定できないの?。というかネット上に情報が少ない(英語圏含めても)。紹介系のページは見つかるけれど、議論や実験的なページはかなりすくない(新しいライブラリというのもあるのだけど)。賑わっていない雰囲気
———————-
とりあえず、シーケンシャルな機能を確認してから判断しよう…
 
 
 

kute.js :イントロ

●jQueryアニメの代わりに

モダンブラウザはjavaScriptやcssの差異が少なく、jQueryなどに頼らなくてもすむようになってきました。しかしアニメ処理、特にシーケンシャルなアニメを実現しようとすると記述量が多くなり面倒です。
 
ということでjQueryに代わってシーケンシャルなアニメを簡単に作成できるようなライブラリを探したところkute.jsが良さそうなので学ぶことにしました。
 
サイトが素敵なのもkuteを選択した大きな理由です。

kute.js :公式サイト
http://thednp.github.io/kute.js/

  
基本的にレガシーブラウザには対応しない。Modernizrも使用しないでとあります(以下ページの最下段)。※IEはver10以前がサポートを打ち切りレガシーとなっている。
→参考:公式サイトget start
→参考:各Windows OSでのInternet Explorerのサポート終了時期
 
サポートしているプロパティは以下。レガシーブラウザに対応しないと言いつつも結構IE9に対応している(3D系はIE10以降)。
→参考:公式サイトSupported Properties

日本語で説明しているサイトは少ないのですが、以下のサイトが詳しいです。
→参考:DOMアニメーションの決定版「KUTE.js」が登場
 
前回まで学んでいたsvgにも対応しています。ただsvgはシンプルな用途に留めた方が良さそうと思っているので積極的な使用はしない。ただvivusよりも複雑なストロークアニメが実現できるので、そのことだけ留意しておこうと思う。
→参考:公式サイト svg plug-in
 

●導入の注意

kute.jsのダウンロードボタンはトップページのイントロアニメが終わった後に表示されます。ダウンロードされるデータはjsファイルの他にサンプルファイルもあるので自習用にダウンロードしておきました。
1031
 
公式サイトのget startedで「kute.jsの読込はbodyタグの最後で読み込むのがベスト」と書いてあったのですが、なんとなくheadタグ内に設定したらエラーになりました。やはりbodyタグの最後に記述のが良さそうです。
→参考:Uncaught TypeError: Cannot read property ‘style’ of null

<script src="../js/kute.min.js"></script>
</body>

 

●スクロール

私の中でスクロールアニメは別カテゴリなので、先にまとめておきます。スムーススクロールの機能で、examplesのVertical Scrollingに説明があります。おまけ的な扱いなのか横スクロール(scrollLeft)には対応していません…。すこしショック。

kute : スムーススクロール
http://jquerystudy.info/kute/0_core/1_scroll.html

 
ソースは以下。jQueryを使わないと記述量が多くなりますね、safariはwindowでなくbody使わないと機能しないし…。あと、なんで横スクロールに対応しないのだろう。
→参考:Scroll Example for KUTE.js

function scrollTo(_id){
	var navHeight = 70;
	var elmRect = document.getElementById(_id).getBoundingClientRect();
	var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
	var pos = elmRect.top + scrollTop - navHeight;
	KUTE.to(scrollElm,{scroll:pos},{easing:'easingCubicOut',duration:1500}).start();
}

 

補足:他のアニメライブラリも試すよ

kute.js以外にもアニメ系のライブラリはたくさんある。kuteの基礎的な学習が済んだら以下のライブラリも試す予定。
 
anime.js
軽量でシンプルなライブラリ。パスに沿ったアニメができる。あと、以下サイトのエフェクトが素敵
→参考:Letter Effects with anime.js
※対応はIE10以降でIE9には対応していない。
 
velocity.js
興味深いのはスプリング系の処理があること。公式サイトのtopで「spring physics」と検索すると説明している部分が見つかります。
jQueryと利用するときはIE8にも対応するが、単体で利用する場合はIE8は対象から外れる。その場合は読込順に注意が必要っぽい。
→参考:Velocity.js not working in IE8

 
おしまい
 
 
 

svgアニメ:ループ

前回の記事で最後と言いつつ、ループ処理について学び残していた…。
 

●アニメは再生後に最初に戻る

ループではないのですが、少し躓いたのでメモ。cssのanimate設定はfill属性をforwardに設定しないと再生終了後に最初のフレームに戻ってしまいます。

CSS animation : デフォルトの設定だと最初に戻る
http://jquerystudy.info/svg/06_loop/fill00.svg

 
そしてfill属性をforwardに設定すると以下のサンプルのように最後のフレームで停止する。

CSS animation : fill属性をforwardに
http://jquerystudy.info/svg/06_loop/fill01.svg

 
svgファイル内に記述したcssは以下のような感じ

#light{
	stroke-width:0; 
	stroke-dasharray: 15 30;
	stroke-dashoffset:20;
	stroke: #000000;
	animation: light_anime 500ms ease-in-out forwards; 
}

forward以外に設定できる値は以下の通り
→参考:MDN animation-fill-mode
 

●ループの設定

ループの設定で覚えるのは2種類。まずはデフォルのとの設定で、最後のフレームになったら最初のフレームに戻るループです。

CSS animation : デフォルトのループ
http://jquerystudy.info/svg/06_loop/loop00.svg

 
svg内のcssは以下の通り。繰り返し回数にinfiniteを設定するととで永遠にループ再生されます。再生回数を設定したい場合はinfiniteの代わりに数値を設定します。

#light{
	stroke-width:0; 
	stroke-dasharray: 15 30;
	stroke-dashoffset:20;
	stroke: #000000;
	animation: light_anime 500ms ease-in-out 0s infinite; 
}

もう1つのループ設定は、最後のフレームに来たら逆再生で最初のフレームに戻るループです。アニメの種類に応じて前述の設定と使い分けましょう。

CSS animation : alternateなループ
http://jquerystudy.info/svg/06_loop/loop01.svg

 
svg内のcssは以下の通り。alternateの設定を追加するだけです。
→参考:MDN animation-direction

#light{
	stroke-width:0; 
	stroke-dasharray: 15 30;
	stroke-dashoffset:20;
	stroke: #000000;
	animation: light_anime 500ms ease-in-out 0s infinite alternate; 
}

 

●一時停止

一時停止もcssで設定できます。以下のサンプルではボタンをクリックするたびに再生/停止が切り替わります。

 
このサンプルはjavaScriptも利用しているのですが、まずはsvg内に設定したcssを確認。以下のように一時停止させたい要素にstopクラスが追加されたらanimation-play-stateをpausedに設定するようにしています。

#light.stop{
	animation-play-state: paused;
}
#bulb.stop{
	animation-play-state: paused;
}

そしてhtml側に記述したjavaScriptでは以下のようにstopクラスを付けたり外したりしているだけです。

function animeToggle(){
	var svg = document.getElementById('sw').contentDocument;
	svg.getElementById('light').classList.toggle("stop");
	svg.getElementById('bulb').classList.toggle("stop");
}

 

●キリの良いところで停止したい

前項のサンプルはボタンをクリックしたタイミングで停止しますが、そうではなくてキリの良いところで停止させたいです。しかし、これは簡単に実現できないようです(webkitは方法があるそうですが…)。
→参考:cssアニメーションの再スタート
 
しかしcssのanimationはイベントが設定できるので、それを利用して無理矢理実現してみました。アニメの長さによって数式を変更する必要があり汎用性は高くないのですが…。
→参考:MDN CSS アニメーション

CSS animation : キリの良いところで停止
http://jquerystudy.info/svg/06_loop/1_pause.html

 
以下はsvg内に記述したjavaScriptの一部です。この_flgの部分でキリの良いポイントを見分けているのですが、アニメの長さによって数式を変更しなければなりません(小数点誤差が出ても問題ない条件式にしたかったので少し回りくどい式になっています)。

var _flg = (e.elapsedTime * 2) % 2 -0.5;
if (_flg &lt; 0){
	light.classList.add("stop");
	bulb.classList.add("stop");
}

※SVGファイル内で「<」を利用するとエラーになるので特殊文字に変換しています。
 
おしまい
 
 
 

クロージャでSVGを管理してみた

今回の技術も対応していないブラウザがあるので、仕事では使えないかもしれませんが…
なんだかパズルゲームのようで楽しくなってきたのでメモ。
svgの記事は一旦、今日が最終回です。

●外部からsvgにjavascriptを設定

前回の記事でhtml側からsvg内にアクセスできることを知りました。それならsvg内にjavascriptを記述しなくても外部から付加できるだろうと思い試しました。

sample : htmlからsvgにjavascriptを付加
http://jquerystudy.info/svg/05_closure/0_func.html

 
まずsvg(switch.svg)内にはcssだけ設定し、javascriptは記述していないことを確認してください(ブラウザの「ソースを表示する」系のメニューでsvgのソースを確認できます)。
 
html側のjavascriptは前回のソースとほとんど同じです。異なるポイントとしては、前回の自分のidを取得する部分が「負荷の高い力業」だったのに対し、今回は引数で受け取り設定しているだけなので負荷が低い点です。

function switchMaster(_id){
	var target_obj = document.getElementById(_id);
	target_obj.contentDocument.id = _id;
	target_obj.contentDocument.onclick = function(){
		var _classList = this.getElementById('light').classList;
		_classList.toggle("switchon");
		var _flg = _classList.contains("switchon");
		window.parent.document.svgState(this.id, _flg);
		
		this.getElementById('bulb').classList.toggle("switchon");
	}
}

 

●setterとgetterの設定

外部から状態(ON/OFF)を設定/取得できるようにクロージャにしてsetterとgetterを付けてみた。サンプルにはsvgとは別にボタンがあり、そこからsvgの状態を取得/変更できます。

sample : svgを外部からアクセスしやすいようにした
http://jquerystudy.info/svg/05_closure/1_clo.html

 
クロージャに関しては以前勉強した(jQueryだけど)。
→参考:クロージャ(1)
 
setterやgetterについては色々悩む。
→参考:オブジェクト指向設計 getter, setterを使うなとはどういうことか
→参考:結局のところgetter/setterは要るのか?要らないのか?
 
おしまい
 
 
 

svgの中にjavascript

●今はまだ使わない方がよい?

以下サイトの最後の部分でsvgファイル内にjavaScriptを記述したサンプルがあります。この方法はfireFoxやoperaで利用できないので、smil同様に仕事では避けるべきなのでしょう。
→参考:HTML5でのSVGファイル操作のおさらい
 
しかし現在(2017.10/26)ではMacのfirefoxやoperaで機能しています。徐々に対応ブラウザも増えていくのでしょう。
 

●firefoxとsvgのクリップパス

今回のサンプルはsvg内のクリップパスを操作しているのですが、これはfirefoxが対応していないためfirefoxではスイッチのデザインが変化しません…。cssを制御する有名なGreenSockのライブラリを利用すれば、この問題も解決できるそうです。
→参考:animating svg masks clip path not working in firefox/
 

●マウスイベント

これまでsvgファイル内にcssを設定してhoverを実現しましたが、今回はjavascriptを利用してhoverを実現しようと思います。

sample : javascriptでhover
http://jquerystudy.info/svg/04_js/hover.svg

 
javaScriptを利用するとはいえデザインの変更はcssで設定します。注意点はhoverの部分で、疑似要素の:hoverではなく、class要素のhoverになっていることです。つまりhoverクラスの付け外しでデザインの変更を行えるようにしています。

<style>
#mask{
	transform:translateX(-250px);
    transition:transform 1s;
}
#mask.hover{
	transform:translateX(0px);
}
</style>

でもってjavaScriptは以下のように記述されています。onmouseover/onmouseoutイベントによってhoverクラスを付けたり外しているだけです。

<script>
var mySvg = document.getElementById('all');
mySvg.onmouseover = function(){
	document.getElementById("mask").classList.add("hover");
};
mySvg.onmouseout = function(){
	document.getElementById("mask").classList.remove("hover");
};
</script>

 

●トグルボタン

前述のサンプルを少し変更してトグルボタンを作りました。クリックするたびにON/OFFが切り替わります。このサンプルもsvg内にjavaScriptを記述しているのでsvgファイル単体で機能します。

 
javaScriptは以下のように記述しています。classListのcontains関数で要素に指定されたclassが負荷されているか確認できるので、それをフラグに表示を切り替えているだけです。

mySvg.onclick = function(){
	var status = document.getElementById("mask").classList.contains("hover");
	if (!status){
		document.getElementById("mask").classList.add("hover");
		//---ONの時に処理したい何か
	}else{
		document.getElementById("mask").classList.remove("hover");
		//---OFFの時に処理したい何か
	}
};

 

●htmlからsvgの関数を実行

ここまでのサンプルはsvg内で完結していましたが、次はhtml側に設定したfunctionを実行してみます。ここからサンプルは直リンのsvgではなくhtmlファイルになります。html側のtoggleボタンをクリックするとsvgの状態が変化します。

sample : htmlからsvgの関数を実行
http://jquerystudy.info/svg/04_js/0_html2svgl.html

 
htmlからsvg内のfunctionをコールするためには一工夫が必要で、以下のサイトが参考になりました。
→参考:Call svg javascript function inside html javascript function
 
svg側のjavascriptの以下1行がポイントです。html側からはsvgのscriptタグにはアクセスできないため、実行したい関数をdocumentに付加する必要があるのです。

document.toggleFunc = toggleFunc;

 
html側は以下のように記述しています。以前の記事に書いたとおりsvg内にアクセスするためにはcontentDocumentが必要となります。

var svg = document.getElementById('svgSwitch');
svg.contentDocument.toggleFunc();

 

●svgからhtmlの関数を実行

次は逆にsvgからhtmlのfunctionを実行してみます。以下のサンプルはsvgをクリックするたびに、その状態をhtmlに表示します。

sample :svgからhtmlの関数を実行
http://jquerystudy.info/svg/04_js/1_svg2html.html

 
まずはhtml側のscriptを確認します、前項と同じようにdocumentの設定が必要となります。svg内部からもhtmlのscriptタグにはアクセスできないためfunctionをdocumentに設定する必要があるのです。

document.svgState = svgState;
function svgState(state){
	var str = state ? "on" : "off";
	document.getElementById('debugText').innerHTML = "svg switch status is " + str + ".";
}

svg側は以下のように記述しています。svg内部からhtmlにアクセスするには以下のようにwindow.parent.documentというパスを記述します。

function toggleFunc(){
	var myClassList = document.getElementById("mask").classList;
	myClassList.toggle("hover");
	window.parent.document.svgState(myClassList.contains("hover"));
}

 

●svgから自分のidを取得

最後に複数のsvgを効率よく管理する仕組みを追加しました。以下のサンプルではsvgのスイッチを切り替えると、上部テキストに「スイッチの状態」が表示されます。

sample :自分のidを管理するsvg
http://jquerystudy.info/svg/04_js/2_id.html

 
まずはhtmlを確認します。ポイントはsvgを配置しているobjectタグのidです。このidをsvg側で取得できれば、管理しやすい構造にできるのです。

<object id="svgSwitch_1" data="toggleFunc3.svg"></object>
<object id="svgSwitch_2" data="toggleFunc3.svg"></object>
<object id="svgSwitch_3" data="toggleFunc3.svg"></object>

最初はparent.idのノリで簡単に取得できると思ったのですが、直接取得できるような仕組みはないようです。なんとかiframeの事例を見つけて、それをsvgに応用することで取得できました。
→参考:How to get parent iframe element from inner page without knowing id?
 
テクニックとしてはかなり力業でです。html内にあるobject要素の内部情報(document)を自分と比較して自分のobjectタグを探し、そのidを取得します。ファイルサイズの大きなsvgでは大きな負荷がかかりそうです…。

var myID;
var objs = window.parent.document.getElementsByTagName("object");
for(var i=0; i&lt;objs.length;i++){
	var f = objs[i];
	var fDoc = f.contentDocument || f.contentWindow.document;
	if(fDoc === document){
		myID = f.getAttribute("id");
	}
}

あとは取得したmyIDをsvgがクリックされたときにhtmlに渡すだけです。

function toggleFunc(){
	var myClassList = document.getElementById("mask").classList;
	myClassList.toggle("hover");
	window.parent.document.svgState(myID, myClassList.contains("hover"));
}

 

●object要素(svg)にcssを付けるときの注意

svg(object要素)にcssを設定するさいにhtml側に設定したら機能しなかった。しかしsvg側に記述したら機能しました。上記サンプルで利用したtoggleFunc3.svgのcssには以下のように記述したのでsvg上にマウスオーバーしたさいにカーソルが変わります。またiOSではタップ時のハイライトが表示されなくなります。

#all{
	-webkit-tap-highlight-color:rgba(0,0,0,0);
	cursor:pointer;
}

 
おしまい
 

フォームでsvgを使いたかった…

●svgを利用したフォームアイテム

これまでの学習で「cssで実現できないような演出のボタン」をsvgで作れそうなことを確認しました。それを発展させてformのトグルボタンもsvgで作成したいと思ったのです。
 
例えば以下のサイトでは素敵な演出のついた「いいねボタン」の例があるのですが、これをformのトグルボタン(ラジオボタン)に組み込めたら素敵だと思ったわけです。
→参考:今こそ導入したいSVGアニメーションの作り方まとめ(全3ページ)

inlineの記述方であればformのトグルボタンとして設定できそうな気もするのですが、その場合はhtmlの可読性が下がり色々編集しにくくなるので避けたいのです。
マイクロインタラクションはインラインsvgが基本っぽい?
→参考:SVGで始めるマイクロインタラクション入門(全2ページ)

 
さらに調査を進めたところ、adobeのブログにてsvgで演出を付けたラジオボタンやチェックボックスの記事がありました。
→参考:CSS vs SVG: Styling Checkboxes and Radio Buttons
→参考:上記のデモページ
 
このサンプルはhtmlの可読性は高いのですが、javaScriptで動的にsvgを制御(svgcheckbx.js)しており難易度は高そうです。javaScriptを利用せずにcssだけでformに組み込めたら嬉しいのですが、現状は無理っぽいです。
 
 
フォームに関しては素直にcss3アニメで対応した方が良さそうですね。
→参考:HTMLとCSSだけで簡単に作れる! トグルボタンの作り方!!
→参考:フォーム周りで覚えておくと便利なCSS Snippets
 
svgは純粋なアニメやシンプルなボタンでの利用に抑えた方が良さそうです。以下のサイトの地図の表示の仕方とか素敵です。
→参考:demo_kanorealestate.html
 
あと何となくマスクも。
→参考:SVGクリッピングマスクにチャレンジ!静止画像も動画も、SVGで切り抜こう!
 
あと再利用(defs/use)についてもメモ。
→参考:図形の定義と再利用

 

●canvasとsvgの違い

svgについて調べるとcanvasとの区別が曖昧になってくる。というわけで調べた。以下のサイトの後半に詳しい説明が載っている。ついでに直ぐしたのcss3との比較も参考になった。
→参考:svg要素の基本的な使い方まとめ

個人的には大がかりな演出はcanvas(create.jsやtree.jsを利用)を使い、ロゴアニメやマイクロインタラクションはsvgを使おう(inlineなsvgは好きになれないので避ける)と思う。
 
あとadobeのcanvasを操作するjsフレームワークとしてはcreate.jsが有名だが、実はsvg用のフレームワークも作成している。
→参考:snap.svg
 
おしまい
 
 

svgアニメ:寄り道(smil)

SVGアニメの実現にはsmilという仕組みもあるのですが…。
 

●svgアニメを設定するsmil

smilはsvgタグ内に記述できる高度なアニメーション処理です。しかしIEどころかEdgeにも対応していないため仕事での使用は避けた方が良さそうです。
→参考:can i use (smil)

利用できるアニメーションは以下のサイトが詳しいです。
→参考:svgにおけるアニメーションの実現
 
以下は往復アニメをリピートさせたサンプルです。

sample : シンプルなsmil
http://jquerystudy.info/svg/03_etc/smil.svg

 
ソースは以下のようになっており、アニメさせる要素(サンプルではrect)の子要素としてanimateタグを設定します。
サンプルでは繰り返し回数を無限(indefinite)に設定し、操作する属性(attributeName)をx、その値(values)を0,-250,0とすることで往復させています。

<rect id="mask" x="-216" y="-45" width="234" height="153">
	<animate repeatCount="indefinite" attributeName="x"
	values="0;-250;0" dur="3s" ></animate>	
</rect>	

 

●マウスイベントでアニメ

smilは簡単にマウスイベントにアニメを設定できます。begin属性で利用できるイベントは以下のサイトが詳しいです。
→参考:MDN web docs :begin

sample : smilでロールオーバーアニメ
http://jquerystudy.info/svg/03_etc/mouse.svg

 
前のサンプルと同じようにアニメさせたい要素の子要素としてanimateタグを設定します。ポイントはbegin属性の値で、ここにイベントを設定します。便利なのは、自分の要素(ここではrect)意外のidも利用できる点で、今回は一番親の要素であるallを利用しました(cssでidを指す記号の#は必要ないことに注意してください)。
 
あと注意点としてはfill属性にfreezeを設定しないとアニメ再生後に最初のフレームに戻ってしまう点です。

<rect id="mask" x="-250" y="-45" width="234" height="153">
	<animate begin="all.mouseover" attributeName="x"  to="0" dur="0.3s"
	fill="freeze"></animate>	
	<animate begin="all.mouseout" attributeName="x"  to="-250" dur="0.3s" 
	fill="freeze"></animate>	
</rect>

 

●javaScriptとの連携

smilの利用を諦めたのはjavaScriptとの連携に向かないためです。beginElementというメソッドで特定の要素に設定されたアニメを再生できるのですが複数のアニメを使い分けることができません。つまり「ボタンAをクリックしたら要素XのアニメA、ボタンBをクリックしたら要素XのアニメBを再生する」といったことができないのです。beginElementのサンプルとしては以下のサイトが詳しいです。
→参考:SVGのpathをJavaScriptでぬるぬる動かしたかった
 
beginElementの引数に何か設定できないかとW3Cのマニュアルを確認したのですが、実行するアニメを振り分けるような処理はありませんでした。
→参考:W3C(animate – dom interface)

●補足

クリップパスのモーフィングを利用したサイト。
→参考:Organic Shape Animations with SVG clipPath
 
 

●素直にCSSを使おう

追記 2017.10/26 : firefoxとクリップパスアニメ
firefoxではクリップパスをcssでアニメさせることは出来ないようです。しかしGreenSockを利用するとなんとかなるっぽいです。
https://greensock.com/forums/topic/12272-animating-svg-masks-clip-path-not-working-in-firefox/

 
 
以下のサンプルはsmilと同じ動作をしますがcssだけで実現しています。

sample : cssでロールオーバーアニメ
http://jquerystudy.info/svg/03_etc/css.svg

 
操作しているのは実際には表示されないclipPathの要素ですが、cssで操作することができます。ただし少し躓いた点があるので、サンプルで少しづつ説明していきます。まず以下のサンプルはcssを設定していないサンプルで、OFFの状態になるようにclipPathの位置を設定しています。

sample : OFFの状態を確認
http://jquerystudy.info/svg/03_etc/css_off.svg

 
ソースは以下のように記述しておりrect要素のx属性の値を-250に設定して画面外に出しています。結果として#mask_onの要素が表示されずグレー表示になります。

<clipPath id="mask_1_">
	<rect id="mask" x="-250" y="-45" width="234" height="153"/>	
</clipPath>

続いてはONの状態。

sample : ONの状態を確認
http://jquerystudy.info/svg/03_etc/css_on.svg

 
このサンプルではx属性の値が0(デフォルトの位置)に設定され、#mask_onの要素がすべて表示されます。

<clipPath id="mask_1_">
	<rect id="mask" x="0" y="-45" width="234" height="153"/>	
</clipPath>

 
でもってcssでこの2つの状態を切り替えるように設定したのが以下のサンプル。

sample : cssアニメの失敗例
http://jquerystudy.info/svg/03_etc/css_ng.svg

 
まずclipPathの位置は以下のように最初はOFFの状態になるようにしました。

<clipPath id="mask_1_">
	<rect id="mask" x="-250" y="-45" width="234" height="153"/>	
</clipPath>

そしてcssの表記は以下のようにしています。translateで勘違いしやすいのは引数は座標を指すのではなく移動量を指す点です。つまり以下のcssだと、最初の段階で、X軸方向にさらに-250してしまうのです。
→参考:CSS3リファレンス-transform:translate

#mask{
	transform:translateX(-250px);
	transition:transform 1s;
}
#all:hover #mask{
	transform:translateX(0px);
}

 
機能するサンプルでは、cssはそのままでclipPathの設定を最初ブルーの状態(つまりx=0)に設定しています。そしてcssのtranslateXによって-250の移動がなされグレーの状態になります。しかし仕様としてイマイチ納得できないのはマウスオーバーでのtranslateXの設定。ここで0を設定することでcssの初期値の位置に戻すのですが、少し分かりにくい気がします(0でなく250と設定しがち…)。

sample : cssでロールオーバーアニメ
http://jquerystudy.info/svg/03_etc/css.svg

 

<clipPath id="mask_1_">
	<rect id="mask" x="0" y="-45" width="234" height="153"/>	
</clipPath>

 
次回はこのサンプルを発展させてform要素のtoggleボタンをsvgで作成したいのですが…。
少し調べたところ無理そう…。
 
 
 

Posted in html5 & css3, study | Tagged , | svgアニメ:寄り道(smil) はコメントを受け付けていません。