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 のインストール後に起こりうる問題の紹介

推薦する

HTML入力で値が変更されたときにリスナーイベントを追加することの簡単な分析

達成される効果多くの場合、入力ボックスの値の変化をリアルタイムで監視し、ブラウザを誘導してウェブサイ...

バックエンドから返される 100,000 個のデータをフロントエンドでより適切に表示するにはどうすればよいですか?

目次予備作業バックエンド構築フロントエンドページダイレクトレンダリングsetTimeout ページン...

Vue での this.$set の動的データバインディングのケーススタディ

インターネット上の this.$set の説明はわかりにくいと感じます。単一データ、オブジェクト、配...

CentOS 7.5 に Python 3.6.6 を最初からインストールするための詳細なチュートリアル

ps: 環境はタイトル通りです依存関係をインストールする yum インストール openssl-de...

Mysql sql スロークエリ監視スクリプトコード例

1. my.cnfを変更する #全体的な効果としては、グローバルがオンになっている場合はテーブルとロ...

MySQLでデータを削除してもディスク領域が解放されないのはなぜですか

目次問題の説明解決問題分析問題の説明MySQL で delete ステートメントを使用してデータを削...

CSS3 レーダースキャンマップのサンプルコード

CSS3 を使用して、クールなレーダースキャン画像を実現します。 コード上で直接: // インデック...

MySQL でデータの重複挿入を回避する 4 つの方法

最も一般的な方法は、フィールドに主キーまたは一意のインデックスを設定することです。重複データを挿入す...

Zabbix による VMware Exsi ホストの監視のグラフィカルな手順

1. 仮想化 vcenter に入り、ブラウザでログインし (クライアントは設定する場所を見つけませ...

Linux システムでの CPU 使用率が高い場合のトラブルシューティングのアイデアと解決策

序文Linux 運用保守エンジニアとして、日々の業務の中で Linux サーバーの CPU 負荷が ...

2つのウェブサイトページ翻訳プラグインの共有

TranslateThis URL: http://translateth.is Google 翻訳...

モバイル Web WAP には Bootstrap と jQuery Mobile のどちらを使用すべきか

問題を解決するBootstrap は、次の問題を解決する CSS フレームワークです。デバイス間での...

dockerでopenGaussデータベースを構成する方法の詳細な説明

Windowsユーザー向けDocker で openGauss を使用するopenGaussイメージ...

Xampp サーバーで MySQL パスワードを変更する方法 (画像付き)

今日、PHP で作業しているときに、Xampp サーバーに付属の mysql データベースを使用する...

HTML要素にフォーカスを設定する方法

コードをコピーコードは次のとおりです。 <本文<フォームアクション="&quo...