ロールオーバー時にボーダーが食い込んでくるようなアニメーションを作る必要があったので、何パターンか考えてみました。ちょうどレクサスのバナー類のようなイメージです。
ADs
あまり使われている印象はありませんが、CSSにはclipというプロパティがあります。
clip・・・・・ボックスを切り抜き表示(クリッピング)する
rect(上,右,下,左)
ボックスの左上端を基準として、上右下左のそれぞれの距離を指定します。
背景に同一サイズの要素を置き、全面に来る画像のclipの値をアニメーションさせることができれば、ちょうどボーダーが食い込んでくるようなアニメーションが実現できそうです。
clipはabsoluteでないと適用できないため、同サイズのspanで囲ってそのspanをrelativeとすることで、位置に影響が出ないようにしています。
また、ロールオーバー時になぜかChromeでのみborder指定がないと背景色が表示されなかったので1pxのborderを指定しています。レイアウトに影響が出そうな場合はbox-sizing:border-boxを指定すれば何とかなりそうです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* clip時の背景となるspan */ .clipanim_wrap { background: #f00; display: inline-block; position: relative; /* borderがないとChromeで背景色がつかない・・・ぐぬぬ */ border: 1px solid #fff; } *:first-child+html .clipanim_wrap { display: inline; zoom: 1; } .clipanim_wrap img { position: absolute; left: 0; top: 0; } |
Javascript側の手順としては、
1.画像をspanで囲う。
2.囲ったspanに対し、mouseenter,mouseleaveをバインドする。
3.mouseenter時にspanの子要素にclipを適用し、mouseleave時に元に戻す。
という流れになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
//CSSプロパティのclipをアニメーションさせることにより、ボーダーがアニメーションしているように見せる $(window).on('load',function(){ //画像と同じwidth,heightのspanで囲う。 $('.clipanim').each(function(key,value){ var h = $(this).outerHeight(); var w = $(this).outerWidth(); $(this).wrap('<span class="clipanim_wrap" style="width: '+w+'px; height: '+h+'px;"></span>'); }); //上記で囲ったspan(span.clipanim_wrap)に対してmouseenter,mouseleaveをバインドする $('.clipanim').on('mouseenter',function(){ $(this).stop(true,true).animate({ fx: 10 },{ duration: 400, step: function(now,fx){ $(this).css({ //上下左右10pxずつ切り抜く clip: 'rect('+now+'px '+($(this).width()-now)+'px '+($(this).height()-now)+'px '+now+'px)' }); } }); }).on('mouseleave',function(){ $(this).animate({ fx: 0 },{ duration: 200, step: function(now,fx){ $(this).css({ clip: 'rect('+now+'px '+($(this).width()-now)+'px '+($(this).height()-now)+'px '+now+'px)' }); } }); }); }); |
アニメーションで使用しているstepという関数については、前回の記事のjQueryによる三角関数を利用したアニメーションの再考(step関数を使ったバージョン)をご参照ください。
ちょっとコードが長くややこしくなってしまいましたので、もっと簡単にできないかと思い考えたところ、border-widthをアニメーションさせることができれば簡単に実現できるのではないかと考えました。
jQueryのanimateはborderWidthに対しても適用できるため、以下のようなコードで枠線の太さを変更するアニメーションが実現できます。
1 2 3 4 5 6 7 8 9 |
$('.borderanim01').on('mouseenter',function(){ $(this).stop(true,true).animate({ borderWidth: '10px' }); }).on('mouseleave',function(){ $(this).stop(true,true).animate({ borderWidth: '0' }); }); |
ただ、borderは画像の外につくため、mouseenter時に画像の位置がずれるという問題があります。
そこで、CSSのbox-sizingプロパティを使用してborderが内側に来るようにします。
1 2 3 4 5 6 |
/* borderWidthのアニメーション時に位置がずれないようにするために必要 */ .boxsizing { box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; } |
box-sizingはborderやpaddingを外側に取るか内側に取るかを指定するプロパティです。
スマートフォンサイトの制作ではよく使われるものではないかと思います。
box-sizing …… ボックスサイズの算出方法を指定する
border-box
パディングとボーダーを幅と高さに含める
borderの太さ分画像が縮小されるという問題はありますが、その点を気にしなければ最も簡単で手っ取り早い方法だと思います。
・・・が、IE7以下ではbox-sizingが効かないので、IE7への対応が必要な場合は使えない方法です。
box-sizingが使えない環境を想定した場合、borderWidthへのアニメーションと同時に画像を縮小させれば同じことができるかと思い以下の様なスクリプトを考えました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
//borderWidthを変更すると同時にwidth/heightを変更して位置がずれないようにする試み //ちょっとギクシャクする $('.borderanim02').on('mouseenter',function(){ $(this).stop(true,true).animate({ borderWidth: '10px', width: '-=20px', height: '-=20px' }); }).on('mouseleave',function(){ $(this).stop(true,true).animate({ borderWidth: '0', width: '+=20px', height: '+=20px' }); }); |
borderの太さ分画像自体を縮小させて位置がずれないようにしようという試みですが、それぞれのアニメーションの実行タイミングがわずかにズレるため、ギクシャクした動きとなってしまいます。実際に使うのは厳しいかもしれません。
そんなわけでいくつか考えてみましたが、個人的には一番がんばって書いたclipを使ってやっていきたい感じです(;´∀`)
ADs
コメントはまだありません。