こんにちは、フロントエンドエンジニアのはっちゃんです。
マスクと言えばclip-pathが有名ですが、IEが全滅なんですよね。まだまだ案件で使うには敷居が高いプロパティな気がしています……。
さて今回はSVGとclip-pathなしで画像にマスクをかけて、さらに簡単なアニメーションを作ってみようと思います。
SVGとclip-pathを使ったマスクは以前まろさんが書いてますので、こちらをご覧ください。 【PC/SPモダンブラウザ全対応】SVGで画像をナナメにクリッピングマスクする方法
考え方
レイヤーを2枚用意し、上のレイヤーをtransformで変形、overflowでマスクをかけます。
下のレイヤーは、上のレイヤーのtransfromに影響されるので、同じ角度だけ戻してあげます。
もうこれだけです! HTMLとCSSは下記になります。
HTML
<div class="object">
<img src="https://82mou.github.io/image/hatsushi_mask.png" alt="">
</div>
CSS
.object {
position: relative;
width: 300px;
height: 300px;
margin: 30px auto 0;
overflow: hidden;
border-radius: 0;
transform: skew(-20deg);
img {
position: absolute;
top: 50%;
left: 50%;
width: 500px;
transform: translate(-50%, -50%) skew(20deg);
}
}
DEMO
See the Pen transform skew mask by k_hatsushi (@hatsushi_kazuya) on CodePen.
ちゃんとマスクされていますね。また、平行四辺形はCSSで作ったものなので、容易にアニメーションさせることができます。
アニメーションさせてみる
CSSのtransitionプロパティを設定して動かしてみましょう。
状態変更用のclassをdata属性に持たせ、四角、丸、ひし形のボタンを作成し、押したら変形するようにします。
HTMLとCSSとJSは下記になります。
HTML
<div id="js-object" class="object">
<img src="https://82mou.github.io/image/hatsushi_mask.png" alt="">
</div>
<ul class="nav">
<li>
<div class="square js-transform" data-object-class="is-square">
<span class="text">square</span>
</div>
</li>
<li>
<div class="circle js-transform" data-object-class="is-circle">
<span class="text">circle</span>
</div>
</li>
<li>
<div class="parallelogram js-transform" data-object-class="is-parallelogram">
<span class="text">parallelogram</span>
</div>
</li>
</ul>
CSS
li {
list-style: none;
}
.object {
position: relative;
width: 300px;
height: 300px;
margin: 30px auto 0;
overflow: hidden;
will-change: transform;
transition: all 0.6s;
&.is-square {
width: 300px;
height: 300px;
border-radius: 0;
transform: skew(0deg);
img {
transform: translate(-50%, -50%) skew(0deg);
}
}
&.is-circle {
width: 300px;
height: 300px;
border-radius: 50%;
transform: skew(0deg);
img {
will-change: transform;
transform: translate(-50%, -50%) skew(0deg);
}
}
&.is-parallelogram {
border-radius: 0;
transform: skew(-20deg);
img {
transform: translate(-50%, -50%) skew(20deg);
}
}
img {
position: absolute;
top: 50%;
left: 50%;
width: 500px;
transform: translate(-50%, -50%) skew(0deg);
transition: all 0.6s;
}
}
.nav {
display: flex;
align-items: center;
justify-content: center;
margin-top: 60px;
li {
padding: 0 30px;
.square {
position: relative;
width: 100px;
height: 100px;
background-color: #8FD5DF;
}
.circle {
position: relative;
width: 100px;
height: 100px;
border-radius: 50%;
background-color: #F2CEE9;
}
.parallelogram {
position: relative;
width: 100px;
height: 100px;
margin: 0 20px;
transform: skew(-30deg);
background-color: #FBF9EC;
.text {
transform: translate(-50%, -50%) skew(30deg);
}
}
}
}
.text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 12px;
}
JS
const $object = $('#js-object'),
$transform = $('.js-transform');
$transform.on('click', (e) => {
$object.removeClass((index, className) => {
return (className.match(/\bis-\S+/g) || []).join(' ')
});
$object.addClass($(e.currentTarget).data('object-class'));
});
完成
See the Pen transform skew mask by k_hatsushi (@hatsushi_kazuya) on CodePen.
平行四辺形を経由する場合のみ若干画像がぶれますが、形状をアニメーションさせることができました。
まとめ
いかがでしたか?
背景色のアニメーションなどを加えるなど、工夫次第で印象に残るアニメーションを実現できそうですね! 何かの参考になれば幸いです、それではまた。
LIGはWebサイト制作を支援しています。ご興味のある方は事業ぺージをぜひご覧ください。