ボタンをホバーすると枠線が変化し、マウスの動きに追従するアニメーション
ホバーでボタンの枠線が変化して、マウスの動きに追従するアニメーションについて学びました。
サンプル
サンプルはこちら↓
コード抜粋
アニメーションに関する部分を抜粋しました↓
.p-button {
position: relative;
font-size:1.5rem;
font-weight: bold;
text-transform: uppercase;
padding:1.5rem 3rem;
--width:100%;
--translateX:0;
&::before {
content:"";
position: absolute;
inset:0;
border:1px solid #000;
pointer-events: none;
border-radius:100vmax;
width:var(--width);
transform:translate(var(--translateX),0);
}
}
const $contactButton = $('.js-button')
const media = gsap.matchMedia()
media.add("(hover:hover) and (pointer:fine)",()=> {
$contactButton.addEventListener('mousemove', (e) => {
const {left,width,height} =e.currentTarget.getBoundingClientRect();
const posX = e.clientX - left;
const controlPosX = posX - height /2;
const interpolatePosX = gsap.utils.interpolate(height / 2 * -1, height / 2,posX /width );
const calcPercent = height/ width * 100;
gsap.to(e.currentTarget, {
"--width":`${calcPercent}%`,
"--translateX":`${controlPosX}px`,
x:interpolatePosX,
duration: .3,
ease:"sine.out"
})
})
$contactButton.addEventListener('mouseleave', (e) => {
gsap.to(e.currentTarget, {
"--width": "100%",
"--translateX": `0`,
x:0,
duration: .3,
ease:"sine.out"
})
})
})
実装ポイント
個人的に実装において大事だと思ったポイントを書きます。
擬似要素のスタイル変更にはCSS変数を使用
擬似要素はCSSによって追加されるため、DOMに存在しないようです。
But since this content was added with CSS, not HTML, it doesn’t exist in the DOM. This is why it's called a pseudo element; because it isn't technically part of the DOM like our hard-coded HTML is; it's added after-the-fact with style rules.
引用元サイト↓
そのため、擬似要素のスタイルを変更する時はCSS変数を使いました。
値の単位を揃える
今回、アニメーションをGSAPで実装しました。
--width
の値を%で揃えないと、ボタンをホバーしたときに幅がビヨ~ンと伸びて意図した動きと異なるため、単位を揃えました。
--width
にボタンの高さをpx
で指定した場合↓
テキスト移動距離の制御
「CONTACT ME」もボタンをホバーしたときに、移動させます。
単純にcontrolPosX
をgsap.to()
のx
に指定すればいいと思ったのですが、
移動しすぎるので、gsap.utils.interpolate("開始値","終了値","割合")
で移動距離を制御しました。
移動しすぎる動きはこちら↓
gsap.utils.interpolate()
についてはこちら↓
border-radius:100vmax;
を指定
今回のボタンは以下の特徴を持ちます。
- ホバーされるまでピル(錠剤)型ボタン
- ホバーされると枠線が円になる
要素の幅や高さが変わっても上記の特徴を維持したいので、50px
のような固定値を指定せず100vmax
を指定しました。
詳しくはこちら↓
Chrome 99 と Safari 15 から無限大 infinity 値が使えるようになっているそうです↓
参考サイト
参考サイトではボタンの枠線用に空のdiv
を使用していましたが、今回は擬似要素で実装してみました↓
Discussion