CATEGORY

SVG

SVG】SVG を Javascript でいじってみる

POLYGON x Javascript

1,776 PV

さて今回は、インライン SVG として取り込んだポリクジラ君上のイベントをキャッチして、何かしらの反応をさせてみたいと思います。

前回はこちら

そうだ、マウスオーバーで回転させよう

軽く思いついてますが、SVG データは座標の基点を親要素のviewboxの左上に持っているため、単純にtransform:rotate()で角度だけを指定しても思い通りの結果は得られません。

CSS でとりあえず :hover に設定してみた

<!-- SVG Whale v03 -->
<div id="svgWhaleV03">
<svg viewBox="0 0 455.545 375.82">
<defs>
    <style type="text/css">
        #svgWhaleV03 {position:relative; width:80%; margin:30px auto;}
        #svgWhaleV03::before {content:''; display:block; padding-top:83%;}
        #svgWhaleV03 svg {position:absolute; top:0px; left:0px; width:100%; height:100%;}
        #svgWhaleV03 svg polygon {-webkit-transition:all 0.3s ease-out; -moz-transition:all 0.3s ease-out; transition:all 0.3s ease-out;}
        #svgWhaleV03 svg polygon:hover {fill:#ff9900; transform:rotate(45deg);}
    </style>
</defs>
<g>
    <polygon points="**~**"/>
</g>
</svg>
</div>
<!-- /SVG Whale v03 -->

こんな感じです。(前回の教訓から<use>参照は捨てましたw)

もちろん基準となる座標を指定すればすむ話なのですが、CSS では難しいので Javascript で解決することにします。

Javascript で中心点座標を設定して、SMIL にしてみた

<!-- SVG Whale v04 -->
<div id="svgWhaleV04">
<svg viewBox="0 0 455.545 375.82">
<defs>
    <style type="text/css">
        #svgWhaleV04 {position:relative; width:80%; margin:30px auto;}
        #svgWhaleV04::before {content:''; display:block; padding-top:83%;}
        #svgWhaleV04 svg {position:absolute; top:0px; left:0px; width:100%; height:100%;}
        #svgWhaleV04 svg polygon {-webkit-transition:all 0.3s ease-out; -moz-transition:all 0.3s ease-out; transition:all 0.3s ease-out;}
        #svgWhaleV04 svg polygon:hover {fill:#ff0000;}
    </style>
</defs>
<g>
    <polygon points="**~**"/><!-- Whale data -->
</g>
</svg>
</div>

<script>
    var svgWhale04 = document.getElementById('svgWhaleV04');
    var svgPoly = svgWhale04.getElementsByTagName('polygon');
    
    for(var i=0; i<svgPoly.length; i++){
        svgPoly[i].addEventListener('mouseover', svgW04());
        svgPoly[i].addEventListener('mouseout', function(){this.removeAttribute('transform')});
    }
    
    function svgW04(){
        return function(){
            var p = this.getAttribute('points').split(' ').join(',').split(',');
            var x,y;
            if(p.lengh = 6){
                x = (parseFloat(p[0]) + parseFloat(p[2]) + parseFloat(p[4])) / 3;
                y = (parseFloat(p[1]) + parseFloat(p[3]) + parseFloat(p[5])) / 3;
            }else if(p.lengh = 8){
                x = (parseFloat(p[0]) + parseFloat(p[2]) + parseFloat(p[4]) + parseFloat(p[6])) / 4;
                y = (parseFloat(p[1]) + parseFloat(p[3]) + parseFloat(p[5]) + parseFloat(p[7])) / 4;
            }

            this.setAttribute('transform', 'rotate(30,' + x + ',' + y + ')');
        }
    }
</script>
<!-- /SVG Whale v04 -->

わぉ!思ってた通りの動きはできたのに、全然カッコ良くないw
※スクリプトが拙いのは初心者なのでご容赦ください。

SMIL のtransformアトリビュート設定だと CSS のtransitionは当然のようにききませんので、なんかマウスに反応しておかしな動きをしてるだけに見えてしまいました。

まぁ基点の設定は上手く出来たっぽいので、次はrotateをなんとかアニメーションにできないかを考えてみます。

Javascript で transform-origin を計算してみるのはどうだろう?

<!-- SVG Whale v05 -->
<div id="svgWhaleV05">
<svg viewBox="0 0 455.545 375.82">
<defs>
    <style type="text/css">
        #svgWhaleV05 {position:relative; width:80%; margin:30px auto;}
        #svgWhaleV05::before {content:''; display:block; padding-top:83%;}
        #svgWhaleV05 svg {position:absolute; top:0px; left:0px; width:100%; height:100%;}
        #svgWhaleV05 svg polygon {-webkit-transition:all 0.3s ease-out; -moz-transition:all 0.3s ease-out; transition:all 0.3s ease-out;}
        #svgWhaleV05 svg polygon:hover {fill:#ff0000;}
    </style>
</defs>
<g>
    <polygon points="**~**"/><!-- Whale data -->
</g>
</svg>
</div>

<script>
    var svgWhale05 = document.getElementById('svgWhaleV05');
    var svgPoly = svgWhale05.getElementsByTagName('polygon');
    for(var i=0; i<svgPoly.length; i++){
        svgPoly[i].addEventListener('mouseover', svgW05());
        svgPoly[i].addEventListener('mouseout', function(){this.removeAttribute('style')});
    }
    
    function svgW05(){
        return function(){
            var p = this.getAttribute('points').split(' ').join(',').split(',');
            var x,y;
            if(p.lengh = 6){
                x = (parseFloat(p[0]) + parseFloat(p[2]) + parseFloat(p[4])) / 3;
                y = (parseFloat(p[1]) + parseFloat(p[3]) + parseFloat(p[5])) / 3;
            }else if(p.lengh = 8){
                x = (parseFloat(p[0]) + parseFloat(p[2]) + parseFloat(p[4]) + parseFloat(p[6])) / 4;
                y = (parseFloat(p[1]) + parseFloat(p[3]) + parseFloat(p[5]) + parseFloat(p[7])) / 4;
            }

            this.setAttribute('style', 'transform-origin:' + x + 'px ' + y + 'px; transform:rotate(30deg);');
        }
    }
</script>
<!-- /SVG Whale v05 -->

うーん、なんだろう、このこれじゃない感は。。。

他にもいろいろパラメーターいじったりしてみたんですが、ちょっと自力に限界を感じたので、今回は諦めました。

Javascript のライブラリ、GSAP とか anime.js とか Snap.svg あたりをチェックして、またチャレンジしてみることにします。
あ、Pixijs ってのも気になるなー。 WebGL か~。

CATEGORY : SVG

GO TOP