CSS でマウスの位置をマッピングし、マウスを動かしてページ要素を制御する (サンプル コード)

CSS でマウスの位置をマッピングし、マウスを動かしてページ要素を制御する (サンプル コード)

マウスの位置をマッピングしたり、ドラッグ効果を実装したりすることは、 JavaScriptで行うことができます。しかし実際には、CSS にはより簡潔な方法があり、 JavaScriptを使用せずに同じ機能を実現できます。

CSS のみを使用してマウスの「クリック アンド ドラッグ」効果を模倣するには、ユーザーのマウスの位置を取得し、それをCSSカスタム プロパティ--positionXおよび--positionYにマップする方法を見てみましょう。具体的な実装手順は以下のとおりです。

初期化

最初のdemoでは--positionXおよび--positionYカスタム プロパティを使用して、要素の幅と高さを設定します。

<div class="content">
  <div class="square"></div>
</div>
*、*::前、*::後 {
  パディング: 0;
  マージン: 0 自動;
  ボックスのサイズ: 境界線ボックス;
}
体 {
  背景色: 黒;
  高さ:100vh;
}
。コンテンツ {
  --位置X: 0;
  --位置Y: 0;
  位置: 絶対;
  上: 0; 右: 0; 下: 0; 左: 0;
  ディスプレイ: フレックス;
  コンテンツの中央揃え: 中央;
  アイテムの位置を中央揃えにします。
}
。四角 {
  幅: 100ピクセル;
  高さ: 100px;
  背景: 白;
} 

これが初期状態です。ここには.contentというコンテナ<div>があり、その幅と高さがbodyを埋めます。これはプロジェクトのコンテンツ本体です。この例では、クラス名が.square<div>マウスで制御する要素です。

コンテンツに 2 つのカスタム プロパティも追加しました。マウスの位置を使用してこれらのプロパティの値を設定し、それらを使用して.square要素の幅と高さを設定します。

マウスの位置のカスタム プロパティを描画したら、それを使ってほぼ何でも実行できます。たとえば、絶対位置に配置された要素のtop/leftを設定したり、 transformプロパティを制御したり、 background-positionを設定したり、 colorを調整したり、疑似要素のコンテンツを設定したりするために使用できます。この記事の最後では、これらのデモのいくつかと、対応するCodepenプロジェクトへのリンクを紹介します。

グリッド

目標は、画面上に目に見えないグリッドを作成し、 :hover疑似クラスを使用して各「セル」をカスタム プロパティの値のセットにマッピングすることです。この時点で、マウス カーソルが画面の右側に移動すると、 --positionXの値は高くなり、マウスが左に移動すると、値は低くなります。 --positionYについても同様です。カーソルが上に移動すると値は低くなり、カーソルが下に移動すると値は高くなります。

グリッド サイズとグリッド分割に関する注意: 実際には、許容できる任意のグリッド サイズを使用できます。値が大きいほど、カスタム プロパティの値は正確になります。しかし、これはグリッド ブロックが増えることも意味します。グリッド ブロックが多すぎると、パフォーマンスの問題が発生する可能性があります。実際のプロジェクトに応じて、適切なバランスでグリッド サイズを調整することが非常に重要です。

ここで、10×10 のグリッド、つまりコンテナー内に合計 100 個のグリッド タイルが必要だとします。 (実際の開発では、 pug などの構文を使用してテーブルをすばやく作成できます。例では、100 個のスペースすべてをdivで表しています。)

<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<!-- 97 個のセルがさらにあります -->
<div class="content">
  <div class="square"></div>
</div>

カスケード関係のため、 .cell要素は.content要素の前に配置されます。

.cellクラスを使用して.squareを制御します。CSS のカスケード関係により、要素は、その子要素 ​​(または子要素の子要素) と、その背後にある兄弟要素 (または兄弟要素の子要素) のみを制御できます。

これは2つのことを意味します:

  • .cell 、制御する要素 (この場合は.square ) の前に置く必要があります。
  • これらの.cellコンテナーに配置することはできません。そうすると、 .content要素は兄弟要素ではなくなります。

セルの配置

.cellsを配置する方法は多数あります。たとえば、 position: absoluteを使用してtopおよびleftプロパティを設定することも、 transformを使用して位置を変換することもできますが、最も簡単なオプションはdisplay: gridを使用することです。

体 {
  背景色: #000;
  高さ:100vh;
  表示: グリッド;
  グリッドテンプレート: repeat(10, 1fr) / repeat(10, 1fr);
}
.セル{
  幅: 100%;
  高さ: 100%;
  境界線: 1px の灰色
  zインデックス: 2;
}

borderは開発中の一時的なもので、画面上でグリッドが見えるようにするためのもので、後で削除されます。
セルをコンテンツの上に表示したいのでz-index非常に重要です。

これまでに完了した内容は次のとおりです。

<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<!-- 97 個のセルがさらにあります -->
<div class="content">
  <div class="square"></div>
</div>
*、*::前、*::後 {
  パディング: 0;
  マージン: 0 自動;
  ボックスのサイズ: 境界線ボックス;
}
体 {
  背景色: 黒;
  高さ:100vh; 
  表示: グリッド;
  グリッドテンプレート: repeat(10, 1fr) / repeat(10, 1fr);
}
.セル{
  幅: 100%;
  高さ: 100%;
  境界線: 1px の灰色
  zインデックス: 2;
 }
。コンテンツ {
  --位置X: 0;
  --位置Y: 0;
  位置: 絶対;
  上: 0; 右: 0; 下: 0; 左: 0;
  ディスプレイ: フレックス;
  コンテンツの中央揃え: 中央;
  アイテムの位置を中央揃えにします。
}
。四角 {
  幅: 100ピクセル;
  高さ: 100px;
  背景: 白;
} 

付加価値

--positionX--positionYの値を.cellを通じて設定したいと思います。

最初の(左の列) .cellhoverと、 --positionX値は0になります。 2 列目の.cellにマウスを移動すると、値は1になります。 3番目は2 、以下同様。

y軸についても同様です。最初の行 (上) の.cellにマウスを移動すると、 --positionY 0になり、2 行目のセルにマウスを移動すると、値は1になります。

白い枠線と左から右の順に並べられた数字が付いた、黒い 10 x 10 の正方形のグリッド。

画像内の数字はグリッド内の各セルの数を表します。単一の.cell (セル 42) を例にとると、 :nth-child()を使用してそれを選択できます。

.cell:n番目の子(42) { }

しかし、いくつか覚えておかなければならないことがあります。

  • このセレクターはセルにhoverたときにのみ有効にしたいので、 :hover添付ファイルを付ける必要がある。
  • セル自体ではなく.content要素を選択したいので、これを行うには一般的な兄弟セレクター~を使用する必要があります。

したがって、42 番目のセルにhoverときに--positionX 1に、 --positionY 3に設定するには、次のようにします。

.cell:nth-child(42):hover ~ .content {
  --位置X: 1;
  --位置Y: 3;
}

しかし、セルが 100 個ある場合、これを 100 回実行したい人がいるでしょうか。 ?これを簡単にする方法はいくつかあります。

  1. Sass @forループを使用して 100 個のセルすべてをループし、計算を実行して、各ループの--positionX値と--positionY値を設定します。
  2. x 軸と y 軸を分離するには、 :nth-child関数表記を使用して各行と列を個別に選択します。
  3. 両方のアプローチを組み合わせて、 Sass @forループと:nth-child関数表記の両方を使用します。

すべてのアプローチには長所と短所がありますが、最もシンプルで最善のアプローチは何かを慎重に考えました。記述するコードの量、コンパイルされたコードの品質、数学的な複雑さに基づいて、私は最終的に 3 番目のアプローチを選択しました。もっと良い方法があれば、コメントで教えてください。

@forループで値を設定する

@for $i は 0 から 10 まで {
 .cell:nth-child(???):hover ~ .content {
    --位置X: #{$i};
  }
  .cell:nth-child(???):hover ~ .content {
    --位置Y: #{$i};
  }
}

これは基本的なループ フレームワークであり、上記で構築したグリッドには 10 行と 10 列があるため、10 回ループする必要があります。グリッドをx軸y軸に分割し、各列に--positionXを設定し、各行に--positionY設定します。ここで必要なのは、適切な数式を見つけて、それを???に入力し、各行と列を選択することです。

まずx軸

上記の数字のグリッド画像に戻ると、第2列のすべてのセルに10的倍數加2数字が含まれていることがわかります。第2列のセルには10的倍數加3ます...

ここで、これを:nth-childの関数式に変換してみましょう。列 2 は次のように表すことができます。

:n番目の子(10n + 2)
  • 10n は 10 の倍数をすべて選択することを意味します。
  • 2 は列番号であり、ループでは列番号を#{$i +1]に置き換えて順番に繰り返します。
.cell:n番目の子(10n + #{$i + 1}):hover ~ .content {
  --位置X: #{$i};
}

ではY軸について考えてみましょう

グリッド画像をもう一度見て、グリッド番号が41與50間の第4行目に注目してください。第5行のグリッド番号は51與60の間になります。各行を選択するには、その範囲を定義する必要があります。たとえば、4 行目の範囲は次のようになります。

.cell:n番目の子(n + 41):n番目の子(-n + 50)

(n + 41)範囲の開始です。
(-n + 50)は範囲の終わりです。
ここで、 $i值を使用して数式内の数字を置き換えます。範囲の開始は(n + #{10 * $i + 1})となり、範囲の終了は(-n + #{10 * ($i + 1)})となります。

したがって、最終的な@forループは次のようになります。

@for $i は 0 から 10 まで {
  .cell:n番目の子(10n + #{$i + 1}):hover ~ .content {
    --位置X: #{$i};
  }
  .cell:n番目の子(n + #{10 * $i + 1}):n番目の子(-n + #{10 * ($i + 1)}):hover ~ .content {
    --位置Y: #{$i};
  }
}

マッピングが完了しました!要素の上にマウスを移動すると、マウスの位置に応じて--positionX--positionYの値が変わります。つまり、これらを使用してコンテンツ内の要素を制御できるということです。

カスタム属性の処理

さて、マウスの位置を 2 つのカスタム プロパティにマッピングしたので、次はそれらを使用して.square要素の幅と高さの値を制御します。

まずは幅から始めましょう。.square .squareの最小幅を100px (つまり、マウス カーソルが画面の左側にあるとき) にするとします。また、マウス カーソルが右に移動するたびに幅20px大きくなるようにしたいとします。

calc()を使用すると、次のことが実現できます。

。四角 {
  幅: calc(100px + var(--positionX) * 20px);
}

高さについても同じことを行いますが、代わりに--positionYを使用します。

。四角 {
  幅: calc(100px + var(--positionX) * 20px);
  高さ: calc(100px + var(--positionY) * 20px);
}

それでおしまい!これで、マウスの位置によって幅と高さが制御されるシンプルな.square要素ができました。マウス カーソルをインターフェイス上で動かすと、それに応じて正方形の幅と高さがどのように変化するかを確認できます。以下は、例全体の完全なコードです。

<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
<!-- 97 個のセルがさらにあります -->
<div class="content">
  <div class="square"></div>
</div>
*、*::前、*::後 {
  パディング: 0;
  マージン: 0 自動;
  ボックスのサイズ: 境界線ボックス;
}
体 {
  背景色: 黒;
  高さ:100vh; 
  表示: グリッド;
  グリッドテンプレート: repeat(10, 1fr) / repeat(10, 1fr);
}
.セル{
  幅: 100%;
  高さ: 100%;
  // 境界線: 1px のソリッド グレー;
  zインデックス: 2;
}
@for $i は 0 から 10 まで {
 .cell:n番目の子(10n + #{$i + 1}):hover ~ .content {
    --positionX: #{$i};
  }
  .cell:n番目の子(n + #{10 * $i + 1}):n番目の子(-n + #{10 * ($i + 1)}):hover ~ .content {
    --位置Y: #{$i};
  }
}
。コンテンツ {
  --位置X: 0;
  --位置Y: 0;
  位置: 絶対;
  上: 0; 右: 0; 下: 0; 左: 0;
  ディスプレイ: フレックス;
  コンテンツの中央揃え: 中央;
  アイテムの位置を中央揃えにします。
}
。四角 {
  幅: calc(100px + var(--positionX) * 20px);
  高さ: calc(100px + var(--positionY) * 20px);
  背景: 白;
  遷移: すべて 0.3 秒;
} 

よりスムーズに見えるように、小さなトランジション効果を追加しました。もちろん、これは必要ありません。 .cell要素のborderもコメントアウトしました。

別のアプローチを試してみましょう

--positionX--positionY 「バイパス」し、最終値を@for循環内で直接設定したい場合があります。この例では、これは次のように実現できます。

@for $i は 0 から 10 まで {
 .cell:n番目の子(10n + #{$i + 1}):hover ~ .content {
    --squareWidth: #{100 + $i * 20}px;
  }
  .cell:n番目の子(n + #{10 * $i + 1}):n番目の子(-n + #{10 * ($i + 1)}):hover ~ .content {
    --squareHeight: #{100 + $i * 20}px;: #{$i};
  }
}

.square要素は次のようにプロパティをカスタマイズできます。

。四角 {
  幅: var(--squareWidth);
  高さ: var(--squareHeight);
}

このアプローチは、より高度なSass数学 (および文字列) 関数を使用できるため、もう少し柔軟ですが、主な原則は例とまったく同じです。

次は何ですか?

まあ、あとはそれをどのように使うかはあなた次第です。可能性は無限大です! CSSでマウスの位置をマッピングする手法をさらに進めることができますか?マウスで変化するページ グラフィックの例をいくつか示します。

飛び跳ねる粒子

3Dテキスト

パース画像

タイプライター効果

記事アドレス: https://www.cnblogs.com/dragonir/p/14557203.html 著者: dragonir

CSS でマウスの位置をマッピングし、マウスを動かしてページ要素を制御する方法についてはこれで終わりです。CSS でマウスの位置をマッピングする関連コンテンツについては、123WORDPRESS.COM の過去の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

<<:  HTML における相対と絶対の使用法と違いの詳細な説明

>>:  Tomcat のインストール後に起こりうる問題の紹介

推薦する

CSSスコープ(スタイル分割)の使用の概要

1. CSSスコープの使用(スタイル分割) Vue では、CSS スタイルを現在のコンポーネントでの...

1 つ以上のフィールドに基づいて重複データを検索する MySQL SQL ステートメント

SQLはテーブル内の重複レコードをすべて見つけます1. テーブルには id と name の 2 つ...

Nginx Rewrite の使用シナリオとコード例の詳細な説明

Nginx Rewriteの使用シナリオ1. URL アドレスジャンプ。たとえば、ユーザーが pm....

Centos7環境でYUMを構築する方法

1. yumソースの設定ファイルを入力します 2.lsで設定ファイルを表示する 3. ディレクトリを...

仮想マシンに Windows Server 2008 オペレーティング システムをインストールする

この記事では、Windows Server オペレーティング システムのインストールと企業でのそのア...

ファイルが存在するかどうかを判断する JavaScript サンプルコード

1. ビジネスシナリオ最近はファイルのアップロードやダウンロードに関する開発をしています。ダウンロー...

Linux環境にMySQLデータベースをインストールする詳細なチュートリアル

1. データベースをインストールする1) yum -y install mysql-server (...

Sublime TextがUbuntuで中国語を入力できない問題の最も簡単な解決策

崇高なSublime Text はコード エディター (Sublime Text2 は有料ソフトウェ...

Linux 時間サブシステムの時間表現例の詳細な説明

序文Linux カーネルでは、元のコードとの互換性を保つため、または特定の仕様に準拠するため、また現...

UniappはBaidu Voiceを使用して録音をテキストに変換する機能を実現

3日間さまざまな困難に遭遇した後、ようやくこの機能を実現しました。正常に実装できる方法を見つける前に...

6つのレイアウトでのFrameLayoutの使用

序文前回はLinearLayoutについて説明しました。今回はFrameLayoutの使い方を説明し...

Linux コマンドを素早く習得する 4 つの方法

Linux マスターになりたいなら、いくつかの Linux コマンドを習得することが不可欠です。 L...

HTMLヘッダータグの使用に関する詳細な説明

HTMLはヘッドとボディの2つの部分で構成されています** ヘッド内のタグはヘッドタグです** タイ...

JavaScriptカスタムオブジェクトメソッドの概要

目次1. オブジェクトを使用してオブジェクトを作成する2. コンストラクタを使用してオブジェクトを作...

js を使用して 2 つの HTML ウィンドウ間で通信する方法

シナリオ: ページAがページBを開くと、ページBで操作した後、ページAは変更されたデータを同期する必...