JavaScript で虫眼鏡の特殊効果を実現

JavaScript で虫眼鏡の特殊効果を実現

達成される効果:マウスを小さな画像の上に置くと、小さなブロックが小さな画像の上に表示され、この小さなブロック内の領域が拡大されて右側の大きな画像に表示されます(下図を参照)。

このエフェクトは主に、マウス座標 e.clientX、e.clientY、オフセット offsetLeft、offsetTop、offsetWidth、sffsetHeight などのプロパティを使用します。

HTML および CSS コード:

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>ドキュメント</title>
    <スタイル>
        *{
            マージン: 0;
            パディング: 0;
        }
        体{
            背景:#2c3e50;

        }
        。包む{
            ディスプレイ: フレックス;            
            位置: 相対的;
            左: 200px;
            上: 30px;
        }
        。小さい{
            幅: 500ピクセル;
            高さ: 300px;
            境界線の半径: 20px;
            オーバーフロー: 非表示;
            位置: 相対的;
            左: 0px;
        }
        .small画像{
            幅: 100%;
            高さ: 100%;
        }
        .small span{
            表示: なし;
            位置: 絶対;  
            左: 0;
            上: 0;      
            幅: 100ピクセル;
            高さ: 100px;
            背景: rgba(0,0,0,0.5);
            カーソル: ポインタ;
            zインデックス: 1;
        }
        。大きい{
            表示: なし;
            幅: 400ピクセル;
            高さ: 400px;
            オーバーフロー: 非表示;
            位置: 相対的;
            左: 50px;
            上: 0;
        }
        .bigimg{
            位置: 絶対;
            左: 0;
            上: 0; 
            幅: 1000ピクセル;
            高さ: 600px;
        }
    </スタイル>
</head>
<本文>
    <div class="wrap">
        <div class="small">
            <img src="img/33.jpg" alt="">
            <span></span>
        </div>
        <div class="big">
            <img src="img/33.jpg" alt="">
        </div>
    </div>

</本文>
</html>

JS部分:

マウスを虫眼鏡(小さな画像上の小さなブロック)に移動すると、右側に大きな画像が表示されます。

// 最大のコンテナ let wrap=document.querySelector('.wrap');
// 小さい画像部分 let smallWrap=document.querySelector('.wrap .small');
smallImg を document.querySelector('.wrap .small img') とします。
smallBox を document.querySelector('.wrap .small span') とします。
// 大きな画像部分 let bigBox=document.querySelector('.wrap .big');
bigImg を document.querySelector('.wrap .big img') とします。
smallWrap.onmouseover=関数(){
       smallBox.style.display="ブロック";
       bigBox.style.display="ブロック";
}

マウスがサムネイル上で移動すると、虫眼鏡も動きを追従します。マウスの座標を取得するには、イベントオブジェクトのevent.clientXとevent.clientYを使用します。

event.clientX と event.clientY を通じて、マウスの位置、親コンテナのオフセット、虫眼鏡のオフセットを取得できます (実際のプロジェクトでは、虫眼鏡にオフセットが設定されている場合があります。このオフセットの影響を除去するには、このオフセットを減算する必要があります)。虫眼鏡エフェクトでは、マウスは常に小さなブロックの中央にあるため、移動位置は次のように取得できます。

smallWrap.onmousemove=関数(e){
            moveX = e.clientX-wrap.offsetLeft-smallWrap.offsetLeft-smallBox.offsetWidth/2 とします。
            moveY=e.clientY-wrap.offsetTop-smallWrap.offsetTop-smallBox.offsetHeight/2 とします。

            maxX=smallWrap.offsetWidth-smallBox.offsetWidth とします。
            maxY = smallWrap.offsetHeight - smallBox.offsetHeight とします。


            smallBox.style.left=moveX+'px'
            smallBox.style.top=moveY+'px'

       }

この時点で、虫眼鏡はマウスの動きに追従します。範囲制限も追加する必要があります。そうしないと、虫眼鏡は小さな画像よりも遠くに移動します。

範囲の制限

smallWrap.onmousemove=関数(e){
            moveX = e.clientX-wrap.offsetLeft-smallWrap.offsetLeft-smallBox.offsetWidth/2 とします。
            moveY=e.clientY-wrap.offsetTop-smallWrap.offsetTop-smallBox.offsetHeight/2 とします。

            maxX = smallWrap.offsetWidth - smallBox.offsetWidth とします。
            maxY=smallWrap.offsetHeight-smallBox.offsetHeight とします。

           
            //範囲制限方法 1/* if(moveX<0){
                移動X=0;
            }そうでない場合(moveX>=maxX){
                移動X=最大X
            }
            移動Y<0の場合{
                移動Y=0;
            }そうでない場合(moveY>=maxY){
                移動Y=最大Y
            } */
             //範囲制限方法2 moveX=Math.min(maxX,Math.max(0,moveX))
            移動Y = Math.min(maxY, Math.max(0, 移動Y))

            smallBox.style.left=moveX+'px'
            smallBox.style.top=moveY+'px'

       }

虫眼鏡がマウスの動きに追従した後、次のステップは、虫眼鏡が動くと大きな画像も動く(大きな画像の移動方向は反対)ことを認識することです。虫眼鏡が動く距離は大きな画像が動く距離に比例し、小さな画像の幅は大きな画像の幅(非表示部分を含む)に比例し、小さな画像が動く最大距離も大きな画像が動く最大距離に比例するため、この2つの式を使用して大きな画像をどれだけ動かすかを計算できます。

虫眼鏡が移動する距離 / 小さい画像の幅 = 大きい画像が移動する距離 / 大きい画像の幅。この式は実装できますが、この効果をもたらす最大移動距離に制限はありません。

したがって、式は次のように記述する必要があります:虫眼鏡が移動する距離 / サムネイルの幅 - 虫眼鏡の幅 (これは虫眼鏡の最大移動範囲です)

虫眼鏡が移動する距離 / (小さい画像の幅 - 虫眼鏡の幅) = 大きい画像が移動する距離 / (大きい画像の幅 - 大きい画像の表示領域)

大きな画像が移動する方向は、虫眼鏡が移動する方向と逆であることに注意してください。

smallWrap.onmousemove=関数(e){
            moveX = e.clientX-wrap.offsetLeft-smallWrap.offsetLeft-smallBox.offsetWidth/2 とします。
            moveY=e.clientY-wrap.offsetTop-smallWrap.offsetTop-smallBox.offsetHeight/2 とします。

            maxX = smallWrap.offsetWidth - smallBox.offsetWidth とします。
            maxY = smallWrap.offsetHeight - smallBox.offsetHeight とします。

           
            //範囲制限方法 1/* if(moveX<0){
                移動X=0;
            }そうでない場合(moveX>=maxX){
                移動X=最大X
            }
            移動Y<0の場合{
                移動Y=0;
            }そうでない場合(moveY>=maxY){
                移動Y=最大Y
            } */
             //範囲制限方法2 moveX=Math.min(maxX,Math.max(0,moveX))
            移動Y = Math.min(maxY, Math.max(0, 移動Y))

            smallBox.style.left=moveX+'px'
            smallBox.style.top=moveY+'px'

            let left=moveX/(smallImg.offsetWidth-smallBox.offsetWidth);//smallImg.offsetWidth-smallBox.offsetWidth 最大移動位置 let top=moveY/(smallImg.offsetHeight-smallBox.offsetHeight);

            bigImg.style.left=-left*(bigImg.offsetWidth-bigBox.offsetWidth)+'px'
            bigImg.style.top=-top*(bigImg.offsetHeight-bigBox.offsetHeight)+'px'
       }

最後に、マウスアウトイベント、マウスアウト、虫眼鏡、大きな画像の非表示を追加します。

smallWrap.onmouseout=関数(){
            smallBox.style.display="なし";
            bigBox.style.display="なし";
       }

完全なコード:

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
    <メタ文字セット="UTF-8">
    <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
    <title>ドキュメント</title>
    <スタイル>
        *{
            マージン: 0;
            パディング: 0;
        }
        体{
            背景:#2c3e50;

        }
        。包む{
            ディスプレイ: フレックス;            
            位置: 相対的;
            左: 200px;
            上: 30px;
        }
        。小さい{
            幅: 500ピクセル;
            高さ: 300px;
            境界線の半径: 20px;
            オーバーフロー: 非表示;
            位置: 相対的;
            左: 100px;
        }
        .small画像{
            幅: 100%;
            高さ: 100%;
        }
        .small span{
            表示: なし;
            位置: 絶対;  
            左: 0;
            上: 0;      
            幅: 100ピクセル;
            高さ: 100px;
            背景: rgba(0,0,0,0.5);
            カーソル: ポインタ;
            zインデックス: 1;
        }
        。大きい{
            表示: なし;
            幅: 400ピクセル;
            高さ: 400px;
            オーバーフロー: 非表示;
            位置: 相対的;
            左: 120px;
            上: 0;
        }
        .bigimg{
            位置: 絶対;
            左: 0;
            上: 0; 
            幅: 1000ピクセル;
            高さ: 600px;
        }
    </スタイル>
</head>
<本文>
    <div class="wrap">
        <div class="small">
            <img src="img/33.jpg" alt="">
            <span></span>
        </div>
        <div class="big">
            <img src="img/33.jpg" alt="">
        </div>
    </div>
    <スクリプト>
        // 最大のコンテナ let wrap=document.querySelector('.wrap');
       // 小さい画像部分 let smallWrap=document.querySelector('.wrap .small');
       smallImg を document.querySelector('.wrap .small img') とします。
       smallBox を document.querySelector('.wrap .small span') とします。
        // 大きな画像部分 let bigBox=document.querySelector('.wrap .big');
       bigImg を document.querySelector('.wrap .big img') とします。
       smallWrap.onmouseover=関数(){
            smallBox.style.display="ブロック";
            bigBox.style.display="ブロック";
       }
       smallWrap.onmousemove=関数(e){
            moveX = e.clientX-wrap.offsetLeft-smallWrap.offsetLeft-smallBox.offsetWidth/2 とします。
            moveY=e.clientY-wrap.offsetTop-smallWrap.offsetTop-smallBox.offsetHeight/2 とします。

            maxX=smallWrap.offsetWidth-smallBox.offsetWidth とします。
            maxY = smallWrap.offsetHeight - smallBox.offsetHeight とします。

           
            //範囲制限方法 1/* if(moveX<0){
                移動X=0;
            }そうでない場合(moveX>=maxX){
                移動X=最大X
            }
            移動Y<0の場合{
                移動Y=0;
            }そうでない場合(moveY>=maxY){
                移動Y=最大Y
            } */
             //範囲制限方法2 moveX=Math.min(maxX,Math.max(0,moveX))
            移動Y = Math.min(maxY, Math.max(0, 移動Y))

            smallBox.style.left=moveX+'px'
            smallBox.style.top=moveY+'px'

            let left=moveX/(smallImg.offsetWidth-smallBox.offsetWidth);//smallImg.offsetWidth-smallBox.offsetWidth 最大移動位置 let top=moveY/(smallImg.offsetHeight-smallBox.offsetHeight);

            bigImg.style.left=-left*(bigImg.offsetWidth-bigBox.offsetWidth)+'px'
            bigImg.style.top=-top*(bigImg.offsetHeight-bigBox.offsetHeight)+'px'
       }
       smallWrap.onmouseout=関数(){
            smallBox.style.display="なし";
            bigBox.style.display="なし";
       }
    </スクリプト>
</本文>
</html>

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • Javascript サンプル プロジェクトでの虫眼鏡効果の実装プロセス
  • JavaScript が Jingdong の虫眼鏡の特殊効果を模倣
  • 虫眼鏡ケースのJavaScriptオブジェクト指向実装
  • JavaScript が Jingdong の虫眼鏡効果を模倣
  • JavaScript が Taobao の虫眼鏡効果を模倣
  • 虫眼鏡効果を実現するJavaScript
  • js で虫眼鏡効果を実現するためのアイデアとコード
  • 虫眼鏡の詳細のJavaScript実装

<<:  フレームセットを使用してワイドスクリーンを中央に配置するためのヒントを共有する

>>:  個人的な意見: デザインについて語る

推薦する

シェルスクリプトは、Docker の半自動コンパイル、パッケージ化、およびリリースアプリケーション操作を構築します。

Docker 公開方法は、DevOps (送信、コンパイル、パッケージ化、リリースなどの一連のイベ...

Vue.js ドラッグ可能なテキストボックスコンポーネントの使用方法の詳細な説明

目次コンポーネントの登録コンポーネントの追加ソースコードドラッグ可能なテキスト ボックスでは、ユーザ...

VUEは底部吸引ボタンを実装

この記事では、VUEの具体的なコードを共有して、下部吸引ボタンを実装する例を紹介します。具体的な内容...

MySQLのよくある間違い

NULL 値によると、MySQL の NULL 値は単にデータがないことを意味します。NULL 値は...

React Native が「NSArray<id<RCTBridgeModule>>型のパラメータを初期化できません」というエラーを報告する (解決方法)

最近、古い RN プロジェクトを Xcode で実行すると、次のコード エラーが報告されました。 &...

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

前提条件: Web開発者プラグインがインストールされている操作手順: [ツール] -> [We...

デザイナーと開発者に役立つ 9 つの超実用的な CSS のヒント

Web デザイナーの頭の中には、仕事に関連する多くの知識が詰まっている必要があります。 CSS は、...

JavaScript 関数はランダムな色の検証コードをカプセル化します (完全なコード)

数字、文字、またはランダムな色の数字と文字の混合で構成される n 桁の確認コード。以下に完全なコード...

シリアルポート使用時のvue-electronの問題解決

エラーは次のとおりです:キャッチされない TypeError: 未定義のプロパティ 'mod...

フラットスタイルを使用してウェブサイトをデザインする方法

フラットなウェブサイト構造の本質はシンプルさです。コンテンツの重要なポイントを強調し、ページの装飾効...

MySQL における distinct と group by の違い

簡単に言うと、distinct は重複を削除するために使用され、group by は統計を集計するよ...

Vue カプセル化コンポーネント アップロード画像コンポーネント

この記事の例では、参考のためにvueアップロード画像コンポーネントの具体的なコードを共有しています。...

MySQL での挿入効率のいくつかの例の比較

序文最近、仕事の都合で、約 1000w の大量のデータを MySQL に挿入する必要があり、時間がか...

MySQL トランザクション分析

取引トランザクションはビジネス ロジックの基本単位です。各トランザクションは一連の SQL ステート...

MYSQL データベースの基礎 - 結合操作の原理

結合では、ネスト ループ結合アルゴリズムが使用されます。ネスト ループ結合には 3 つの種類がありま...