##やりたかったこと
角丸要素にマスクをかけて、中の子要素をCSSでアニメーションさせたい
どんなアニメーションかというと、要素の中に小さな円があって、それが要素内をぶわぁ〜って広がっていくような感じ。
##ハマったポイント
子要素に対してマスクはかかっていたが、アニメーションさせた時に角丸の四隅がマスクされない。
##失敗コードその1
<div class="box">
click me!
<div class="boxInner"></div>
</div>
.box{
text-align:center;
width:400px;
height:400px;
background:#efefef;
border-radius:50px;
position:relative;
overflow:hidden;
margin:10% auto;
}
.boxInner{
content:'aaa';
width:100px;
height:100px;
background:#ff0000;
border-radius:50%;
position:absolute;
top:-2%;
left:-2%;
&.anm{
animation-name: slidein;
animation-duration: 4s;
}
}
@keyframes slidein {
0% {
top:-200%;
left:-200%;
opacity:1;
width: 0%;
height:0%;
}
100%{
top:-100%;
left:-100%;
opacity:0;
width: 500%;
height:500%;
}
}
$(function(){
$('.box').on('click',function(){
$('.boxInner').toggleClass('anm');
})
});
※javascriptはクリックした時にクラスを追加するためだけに書いています。
###原因
keyframes内でopacityの値を入れているとマスクされないようです。
opacityを外したら四隅はマスクされました。
でも、動作的に円が中心から広がっていくようなイメージではない(widthを広げている)ため、何かイメージと違うのでこれはボツ。
##失敗コードその2
<div class="box">
click me!
<div class="boxInner"></div>
</div>
.box{
text-align:center;
width:400px;
height:400px;
background:#efefef;
border-radius:50px;
position:relative;
overflow:hidden;
margin:10% auto;
}
.boxInner{
width:100px;
height:100px;
background:#ff0000;
border-radius:50%;
position:absolute;
top:-2%;
left:-2%;
&.anm{
animation-name: slidein;
animation-duration: 2s;
}
}
@keyframes slidein {
0% {
transform:scale(0.1);
}
100% {
background:#FFCADE;
transform:scale(50);
}
}
$(function(){
$('.box').on('click',function(){
$('.boxInner').toggleClass('anm');
})
});
widthを広げるのではなく、transform:scaleで拡大させる作戦。
動作はイメージ通り、でも四隅がマスクされない問題勃発。。。
###原因
keyframes内でtransformを設定しているとこうなるらしい。
##完全に詰んだ・・・orz
この手のエフェクトはGoogleのマテリアルデザインなんかでも採用されていたりするので、色んな所で見たりもしていたけど、
まさか角丸だとマスクされないとは・・・
先人たちはこのピンチをどのように切り抜けてきたのであろうかと、
悩みながら試行錯誤を繰り返して約半日。
9割9部諦めていた時に...
##神は降臨した!
border-radiusで丸くした部分にoverflow:hiddenが効かない対処法
神様仏様qiita様!
やはり、同じ問題を抱えて解決された方がいらっしゃった!
cssに「mask-image」なるプロパティが存在していたのですね!
画像で要素にマスクがかけられるようだ!
これを使って修正してみた!
##成功コード
<div class="box">
click me!
<div class="boxInner"></div>
</div>
.box{
text-align:center;
width:400px;
height:400px;
background:#efefef;
border-radius:50px;
position:relative;
overflow:hidden;
margin:10% auto;
-webkit-mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
mask-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAA5JREFUeNpiYGBgAAgwAAAEAAGbA+oJAAAAAElFTkSuQmCC);
}
.boxInner{
width:100px;
height:100px;
background:#ff0000;
border-radius:50%;
position:absolute;
top:-2%;
left:-2%;
&.anm{
animation-name: slidein;
animation-duration: 2s;
}
}
@keyframes slidein {
0% {
transform:scale(0.1);
}
100% {
background:#FFCADE;
transform:scale(50);
}
}
$(function(){
$('.box').on('click',function(){
$('.boxInner').toggleClass('anm');
})
});
できた!!できたよ!!!!
求めていたのはまさにこれ!
たったに行のコードを追加しただけで解決しました!
##8/23追記
mask-image
を使わなくても親要素の .box
に z-index
を指定してあげたらマスクがかかるようです。
【参考】
http://codepen.io/geckotang/pen/NAVXmQ
http://codepen.io/geckotang/pen/XKwkAr
>GeckoTang様
ご指摘ありがとうございました!
##振り返り
今回の一件で、今まで要素にマスクをかける方法がoverflow:hidden
のみだと思っていたが、
mask-image
という新たな引き出しを得ることが出来た。
しかも、これだと画像で要素がくり抜けるので、いろんなことにも応用が効きそう!
さらに色々調べていくと、svgを使ってマスクをかけることも出来るみたい(http://qiita.com/C058/items/25f0c5e362ba7a5e99e3 )なので、
今度はこちらも試してみたい!