CSS3+JS による虫眼鏡モードの完璧な実装の詳細説明

CSS3+JS による虫眼鏡モードの完璧な実装の詳細説明

約 1 年前、私は「虫眼鏡効果を模倣するいくつかの方法の原理の分析」という記事を書きました。当時、自分のスキルは十分に高く、誇りに思っていたので、このような自慢げなタイトルを付けました。実際には、CSS の 2 つのアニメーション メソッド、つまり変換とアニメーションを紹介しただけでした。もちろん、達成された効果も非常に単純なものでした...恥ずかしいです。

技術の進歩により、純粋な JS を使用してキャンバス拡大鏡と別の「Taobao スタイル」モデルを徐々に実現しましたが、実装が複雑すぎて、ほとんどの JS ロジックに依存していたため、まだ不十分でした。動きと表示効果はすべて JS に依存し、オフセットは JS によって計算され、スタイルがレンダリングされていました。

しかし、CSS3 カスタム変数の出現により、希望が生まれました。

まず効果を見てみましょう:

虫眼鏡のCSS3+JS実装

コア実装:

  • CSS 関数、例: calc() - 動的計算、 var() - カスタム変数の使用
  • CSS 疑似要素: ::before/after — 制御しやすく、ドキュメントフローに依存せず、レンダリングも簡単
  • JS API: offsetX/offsetY : 親ノード領域の左上隅からの相対位置

実際、私たちが具体的に実現したいのは、マウスが移動すると、小さな円が(マウスに追従して)表示され、この小さな円が移動する場所の画像領域が対応する倍数に拡大され、円内に表示されることです。

なぜオフセット API を使用するのですか?
実際、上記の説明によれば、マウスの左オフセットと上オフセットをリアルタイムで取得する必要があり、これら 2 つのオフセットは親ノードを基準としています。親ノードに対する虫眼鏡コンテンツの表示位置はcalc()を使用して左オフセットと上オフセットを組み合わせることで計算できます。
マウス イベント オブジェクトで、js が次の API を提供していることは簡単にわかります。

  • screenX/screenY : 画面領域の左上隅を基準とした位置。スクロールが発生する場合は、この領域を基準とした位置になります。
  • pageX/pageY : ウェブページ領域の左上隅からの相対位置
  • clientX/clientY : ブラウザの表示領域の左上隅からの相対位置
  • offsetX/offsetY : 親ノード領域の左上隅からの相対位置。親ノードがない場合は、 <html>または<body>からの相対位置。

しかし、比較すると、要件を満たすのは「親要素に対する相対的な」オフセットだけです。

<div class="ブルース">
    <div class="拡大鏡"></div>
</div>
拡大鏡を document.querySelector(".magnifier"); とします。
magnifier.addEventListener("mousemove",e=>{
	//「ミラー」の小さな円の動きを制御します});

虫眼鏡は、元の画像を N 倍に拡大し、一定の領域を比例的に遮断して、上記のオフセットを通じてコン​​テンツを表示することでコンテンツを表示します。

まず、関連する CSS 変数を定義します。倍率を 2.5 倍に設定しているので、拡大された画像の幅と高さも元の幅と高さの 2.5 倍になります。 --x--yに分かれた 2 つの変数を宣言します。

:根{
    --比率: 2.5;
    --box-w: 600px;
    --box-h: 400px;
    --outbox-w: calc(var(--box-w) * var(--ratio));
    --outbox-h: calc(var(--box-h) * var(--ratio));
}
.ブルース{
    上マージン: 50px;
}
.拡大鏡{
    --x:0;
    --y:0;
    オーバーフロー: 非表示;
    位置: 相対的;
    幅: var(--box-w);
    高さ: var(--box-h);
    背景: url("img/nan.png") 繰り返しなし center/100% 100%;
    カーソル: 取得;
}

画像は背景画像として表示されるため、サイズを簡単に制御できます。

明らかに、このシナリオでは、虫眼鏡のコンテナーとして子ノードを挿入する必要はありません。 ::before使用するだけです。

虫眼鏡は、使用時には幅と高さが 100 ピクセルになり、使用していない時には幅と高さが 0 ピクセルになります。マウスの移動に伴う虫眼鏡の位置は、絶対位置指定、つまり left と top を宣言し、次にtransform:translate(-50%,-50%)を宣言して虫眼鏡の位置を埋めることで配置され、虫眼鏡の中心がマウス カーソルの位置と一致するようになります。 left と top は虫眼鏡の位置を特定するために宣言されているので、 will-changeも宣言して left と top の変更によって発生するパフォーマンスの問題を改善できます。
これらの問題を解決するために CSS を使用するもう 1 つの利点は、疑似要素/疑似クラスの助けを借りて、「重い」JavaScript に頼るのではなく、CSS を使用してより詳細な問題の一部を解決できることです。たとえば、マウスがホバー スタイルに入ります。

.magnifier::before{
    --サイズ: 0;
    位置: 絶対;
    左: var(--x);
    上: var(--y);
    境界線の半径: 100%;
    幅: var(--size);
    高さ: var(--size);
    ボックスの影: 1px 1px 3px rgba(0,0,0,.5);
    コンテンツ: "";
    変更されます:左、上;
    変換: translate(-50%,-50%);
}
.magnifier:hover::before{
    --サイズ: 100px;
}

次に、背景を使用して虫眼鏡コンテンツを実装(表示)します。 2.5倍の拡大率に合わせて、 size: --outbox-w --outbox-hを宣言し、position-xとposition-yで背景を移動します。最終的には、 background:#333 url(背景圖片) no-repeat var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h)
このうち、 --scale-x と --scale-y は、マウスの移動に応じて背景の位置を変更するために使用される position-x と position-y (つまりbackground-position ) に対応します。

--scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x));
--scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y));

上記の mousemove 関数内のミラーの「位置座標」は、次のように記述できます。

e.target.style.setProperty("--x",`${e.offsetX}px`);
e.target.style.setProperty("--y",`${e.offsetY}px`);

とても簡単〜

最終的な CSS コンテンツは次のようになります。

:根{
    --比率: 2.5;
    --box-w: 600px;
    --box-h: 400px;
    --outbox-w: calc(var(--box-w) * var(--ratio));
    --outbox-h: calc(var(--box-h) * var(--ratio));
}
.ブルース{
    上マージン: 50px;
}
.拡大鏡{
    --x:0;
    --y:0;
    オーバーフロー: 非表示;
    位置: 相対的;
    幅: var(--box-w);
    高さ: var(--box-h);
    背景: url("img/nan.png") 繰り返しなし center/100% 100%;
    カーソル: 取得;
}
.magnifier::before{
    --サイズ: 0;
    --scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x));
    --scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y));
    位置: 絶対;
    左: var(--x);
    上: var(--y);
    境界線の半径: 100%;
    幅: var(--size);
    高さ: var(--size);
    背景: #333 url("img/nan.png") 繰り返しなし var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h);
    ボックスの影: 1px 1px 3px rgba(0,0,0,.5);
    コンテンツ: "";
    変更されます:左、上;
    変換: translate(-50%,-50%);
}
.magnifier:hover::before{
    --サイズ: 100px;
}

::before 2 倍のサイズの画像を使用する場合は、background の--outbox-w--outbox-h元の--box-w--box-hに置き換えて、適切な調整を行ってください。

虫眼鏡の内容に注目してください。これは単なる画像の拡大ではなく、 var(--size) / var(--ratio)コードがあることを示しています。
CSS での CSS3 カスタム変数の変更について: 「同じレベルおよび同じ所属」の範囲内でのみ変更および正常に表示できると私は依然として考えています。

CSS3+JS で虫眼鏡モードを完璧に実装する方法についての記事はこれで終わりです。CSS3+JS 虫眼鏡に関するより関連性の高いコンテンツについては、123WORDPRESS.COM で過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後も 123WORDPRESS.COM を応援していただければ幸いです。

<<:  FirefoxのWeb開発者を使用してWebページのスタイルを無効にする方法

>>:  React Router V6 のアップデート

推薦する

MySQLの重複排除方法

MySQLの重複排除方法【初級】繰り返しのセリフが少ないdistinctive を使用してそれらを見...

Vueの学習手順

目次1. v-text (v-instruction name = "variable&q...

js 日付と時刻のフォーマット方法の例

js 日付時刻形式日付と時刻を指定された形式に変換します。例: YYYY-mm-dd HH:MM は...

get メソッドによる HTML フォームの値転送の例

google.htmlインターフェースは図の通りですコードは図のとおりです: (比較的シンプルで、入...

Linux での nginx のインストール、展開、使用方法の詳細な説明

目次1. ダウンロード2. 展開3. Nginxログ関連の設定4. ファイルダウンローダーとして n...

Webデザインチュートリアル(6):デザインへの情熱を持ち続ける

<br />前の記事:Webデザインチュートリアル(5):Webビジュアルデザイン。 1...

興味深いカウントダウン効果を実現するjs

js興味深いカウントダウンケース、参考までに、具体的な内容は次のとおりですコード: <!DO...

Alibaba Cloud Server への Web プロジェクトのデプロイについて (5 つの手順)

1.まずAlibaba Cloudのウェブサイトにログインしてアカウントを登録し、サーバータイプを...

よく使用される Linux コマンドの完全なリスト (推奨コレクション)

目次1. システム情報2. シャットダウン(システムのシャットダウン、再起動、ログアウト) 3. フ...

いくつかの一般的な CSS レイアウト (要約)

まとめこの記事では、次の一般的なレイアウトを紹介します。 3 列レイアウトを実装する方法は多数ありま...

Webフロントエンド開発経験の概要

XMLファイルは、可能な限りutf-8でエンコードする必要があります。gb2312には、?など、保存...

MySQL セキュリティ管理の詳細

目次1. 順番に紹介する2. ユーザーを作成する3. ユーザーアカウントを削除する4. アクセス権5...