虫眼鏡コンポーネントのネイティブ js 実装

虫眼鏡コンポーネントのネイティブ js 実装

この記事の例では、参考までに虫眼鏡コンポーネントを開発するためのjsの具体的なコードを共有しています。具体的な内容は次のとおりです。

機能要件:

1. 画像配列に基づいてアイコン リストを作成します。
2. マウスをアイコンの上に移動すると、現在のアイコンに赤い枠線が追加されます。
3. マウスをアイコンの上に移動すると、対応する画像が上部の画像領域に表示され、拡大された画像の内容が右側に表示されます。
4. マウスを画像領域内で動かすと、右側にズーム効果が得られます。
5. 下のアイコン リストで、左ボタンと右ボタンをクリックしてページをめくります。
6. アイコンの内容が 1 ページに収まらない場合は、最後のアイコンの位置にのみ移動します。

効果を確認するために、JD.com の詳細ページを例に挙げてみましょう。

虫眼鏡の内容は Zoom.js ファイルに記述されており、下のアイコンリストの内容は IconList.js ファイルに記述されています。下のアイコンにマウスをホバーすると、虫眼鏡内の div の背景画像を変更する必要があります。ここではイベントスローを使用します。

コードは以下に添付されています:

HTML構造:

<!DOCTYPE html>
<html lang="ja">
<ヘッド>
 <メタ文字セット="UTF-8">
 <meta name="viewport" content="width=デバイス幅、初期スケール=1.0">
 <title>ズーム</title>
</head>
<本文>
 <スクリプトタイプ="モジュール">
  './js/Zoom.js' から Zoom をインポートします。
  //アイコン配列 let list=["a_icon.jpg","e_icon.jpg","f_icon.jpg","g_icon.jpg","h_icon.jpg","i_icon.jpg","j_icon.jpg",];
  初期化();
  関数init(){
   zoom = new Zoom(list,"./img/"); を設定します。
   zoom.appendTo("本文");
  }
 </スクリプト>
</本文>
</html>

Zoom.js ファイルで、虫眼鏡コンポーネントを作成します。

「./Utils.js」からUtilsをインポートします。
'./IconList.js' から IconList をインポートします。
デフォルトクラス Zoom をエクスポートする{
 静的スタイル=false;
 静的small_width=450;
 静的マスク幅=303.75;
 静的ズーム幅=540;
 静的 SET_BG_IMG="set_bg_img";
 コンストラクター(_list,_basePath){
  _basePath の場合、_list は _list.map(item=>_basePath+item) になります。
  //外側の div コンテナーを作成します。this.elem=this.createE();
  //イベントをリッスンし、zoomSmall の背景画像を変更します。document.addEventListener(Zoom.SET_BG_IMG, e=>this.setBgImg(e));
  //以下のアイコン リストを作成します。this.createIconList(_list,this.elem);
 }
 作成E(){
  //外側の div コンテナーを作成します。let div=Utils.createE("div");
  div.className="zoomContainer";
  div.innerHTML=`<div class="zoomSmall" id="zoomSmall"><div class="zoomMask" id="zoomMask"></div></div>
  <div class="zoomContent" id="zoomCont"></div>`;
  //スタイルを設定しますZoom.setStyle();
  //スタイルを取得します Utils.getIdElem(div,this);
  //マウス エントリ イベントをリッスンします this.zoomSmall.addEventListener("mouseenter",e=>this.mouseHandler(e));
  div を返します。
 }
 親に追加{
  Utils.appendTo(this.elem,parent);
 }
 setBgImg(e){
  //背景画像を設定します this.zoomSmall.style.backgroundImage=`url(${e.src})`;
  this.zoomCont.style.backgroundImage=`url(${e.src})`;
 }
 アイコンリストを作成します(リスト、親){
  //以下のアイコン リストを作成します。let iconList=new IconList(list);
  Utils.appendTo(iconList.elem,parent);
 }
 マウスハンドラ(e){
  スイッチ (e.type) {
   ケース「マウス入力」:
    //マウスがスライドインすると、マスクと右側の大きな画像が表示されます this.zoomMask.style.display="block";
    this.zoomCont.style.display="ブロック";
    //マウスの動きとスライドアウト イベントをリッスンします this.mouseHandlers=e=>this.mouseHandler(e);
    this.zoomSmall.addEventListener("mousemove",this.mouseHandlers);
    this.zoomSmall.addEventListener("mouseleave",this.mouseHandlers);
    壊す;
   ケース「マウス移動」:
    //マスクの移動 this.zoomMaskMove(e);
    壊す;
   ケース「マウスリーブ」:
    //マウスが移動すると、マスクと右側の大きな画像が表示されます this.zoomMask.style.display="none";
    this.zoomCont.style.display="なし";
    //マウスの移動とスライドアウトのイベントを削除します。this.zoomSmall.removeEventListener("mousemove",this.mouseHandlers);
    this.zoomSmall.removeEventListener("mouseleave",this.mouseHandlers);
    壊す;
  }
 }
 ズームマスク移動(e){
  //マスクの動き let rect = this.elem.getBoundingClientRect();
  //let と top の値を計算します。これは、マウスの座標 (親コンテナーの左の値) とマスクの幅の半分に等しくなります。let x=e.clientX-rect.x-Zoom.mask_width/2;
  y = e.clientY-rect.y-Zoom.mask_width/2 とします。
  //左と上の範囲を判断する if(x<0) x=0;
  x>Zoom.small_width-Zoom.mask_widthの場合、x=Zoom.small_width-Zoom.mask_width;
  y<0の場合、y=0;
  y>Zoom.small_width-Zoom.mask_widthの場合、y=Zoom.small_width-Zoom.mask_width;
  this.zoomMask.style.left=x+"px";
  this.zoomMask.style.top=y+"px";
  // 大きな画像を移動する this.zoomContMove(x,y);
 }
 ズームコントムーブ(_x,_y){
  // 大きな画像の背景の位置を計算します。式: ズーム幅/マスク幅=ズーム背景の左値/マスクの左値 let x=-Zoom.zoom_width/Zoom.mask_width*_x;
  y = -Zoom.zoom_width / Zoom.mask_width * _y とします。
  this.zoomCont.style.backgroundPosition=x+"px "+y+"px";
 }
 静的setStyle(){
  //スタイルを設定する if(Zoom.styles) return;
  ズームスタイル=true;
  Utils.insertCss(".zoomContainer",{
   幅:Zoom.small_width+"px",
   高さ:Zoom.small_width+"px",
   位置:"相対"
  })
  Utils.insertCss(".zoomSmall",{
   幅:Zoom.small_width+"px",
   高さ:Zoom.small_width+"px",
   境界線: "1px 実線 #000",
   背景サイズ: "100% 100%",
   位置:"絶対",
   左:"0px",
   上:"0px"
  })
  Utils.insertCss(".zoomMask",{
   幅: this.mask_width + "px",
   高さ: this.mask_width + "px",
   背景色: "rgba(200,170,0,0.3)"、
   位置: "絶対"、
   左: "0px",
   上: "0px",
   表示: 「なし」
  })
  Utils.insertCss(".zoomContent",{
   幅: this.zoom_width + "px",
   高さ: this.zoom_width + "px",
   境界線: "1px 実線 #ccc",
   位置: "絶対"、
   左: (this.small_width + 2) + "px",
   上: "0px",
   表示: 「なし」
  })
 }
}

IconList.js ファイルを使用して、以下のアイコン リストを作成し、ページめくり効果を完成させます。

「./Utils.js」からUtilsをインポートします。
「./Zoom.js」からZoomをインポートします。
デフォルトクラスIconListをエクスポートする{
 静的スタイル=false;
 static num=5;//ページあたりに表示されるアイコンの数 static gap=0;//リストの左右の間隔を示します position=0;//現在アイコンが表示されているページ x=0;//リストの左の値 prepIcon;//最後にクリックされたアイコン static SET_BG_IMG="set_bg_img";
 コンストラクタ(リスト){
  this.list=リスト;
  this.elem = this.createE();
 }
 作成E(){
  // 外側のコンテナを作成します let div=Utils.createE("div");
  div.className="アイコンコンテナ";
  div.innerHTML=`<img class="prevBtn" src="./img/prev.png"><div class="iconListCont">${this.createIcon()}</div><img class="nextBtn" src="./img/next.png">`;
  //CSS スタイルを設定する IconList.setStyles(this.list);
  //要素を取得します Utils.getIdElem(div,this);
  //外側のコンテナはクリック イベントをリッスンします div.addEventListener("click",e=>this.clickHandler(e));
  //アイコン リストはマウス オーバー イベントを監視します。this.iconList.addEventListener("mouseover",e=>this.mouseHandler(e));
  //デフォルトでは、最初のアイコンの境界線が表示されます this.setIconState(this.iconList.firstElementChild);
  // デフォルトでは最初の画像が表示されます this.setBgImg(this.iconList.firstElementChild.firstElementChild);
  div を返します。
 }
 アイコンを作成します(){
  //アイコン リストを作成します let str=`<ul class="iconList clearfix" id="iconList">`;
  this.list.forEach(item=>{
   str+=`<li><img src="${item}"></li>`;
  })
  str+="</ul>";
  str を返します。
 }
 クリックハンドラ(e){
  src = e.target.src; とします。
  //クリックされたボタンが左または右のボタンでない場合は、直接ジャンプします。if(!/prev/.test(src)&&!/next/.test(src)) return;
  //各 li の実際の幅、幅 + 境界線 + 余白
  liWidth=54+4+IconList.gap とします。
  //page は整数ページの合計数です。let page=Math.floor(this.list.length/IconList.num)-1;
  //remainder は 1 ページに足りない残りのアイコンの数です。let remainder=this.list.length%IconList.num;
  if(/prev/.test(src)){
   //前のページボタンがクリックされた場合 if(this.x===0) return;
   //最後のページへ移動 if(this.position===0&&remainder>0){
    // 移動距離と残りのアイコンの合計は、li width * this.x+=liWidth*remainder に等しくなります。
   }
   そうでない場合(this.position<=page){
    this.position--;
    //移動距離 + liの幅 * 1ページあたりに表示されるアイコンの数 (5)
    this.x+=liWidth*IconList.num;
   }
  }そうでない場合(/next/.test(src)){
   //次のページボタンがクリックされた場合 if(this.x===-(this.list.length-IconList.num)*liWidth) return;
   if(this.position===page&&remainder>0){
    // 移動距離から li の幅を引いた値 * 残りのアイコンの数 this.x-=liWidth*remainder;
   }
   そうでない場合、(this.position<page){
    this.position++;
    // 移動距離から li の幅を引いた値 * 1 ページあたりに表示されるアイコンの数 (5)
    this.x-=liWidth*IconList.num;
   }
  }
  //アイコン リストの左の値を設定します。this.iconList.style.left=this.x+"px";
 }
 マウスハンドラ(e){
  // スライドしたタグが Img タグでない場合は、そのまま終了します。if(e.target.constructor!==HTMLImageElement) return;
  //背景画像を設定します this.setBgImg(e.target);
  //現在のスライドアイコンのスタイルを設定します。this.setIconState(e.target.parentElement);
 }
 setIconState(ターゲット){
  //前のスクロール アイコンのアクティブ スタイルを削除します if(this.prepIcon) Utils.removeClass(this.prepIcon,"active");
  //現在のスライドオブジェクトを this.prepIcon に割り当てます
  this.prepIcon=ターゲット;
  //現在のスライド アイコンにアクティブ スタイルを追加します Utils.addClass(this.prepIcon,"active");
 }
 setBgImg(ターゲット){
  //イベントをスローし、現在の画像の src を渡します。let src=target.src.replace("_icon","");
  evt = 新しいイベント (IconList.SET_BG_IMG) を作成します。
  evt.src = ソース;
  ドキュメントのイベントをディスパッチします。
 }
 静的setStyles(リスト){
  //スタイルを設定する if(IconList.styles) return;
  アイコンリスト.styles=true;
  Utils.insertCss(".iconContainer",{
   幅:Zoom.small_width+2+"px",
   高さ: "58px",
   位置: "絶対"、
   上: Zoom.small_width+2+"px",
   左: "0px",
  })
  Utils.insertCss(".iconContainer>img",{
   幅:"22px",
   高さ:"32px",
   カーソル:"ポインタ",
   位置:"絶対",
   上:"13px",
  })
  Utils.insertCss(".prevBtn",{
   左:"8px"
  })
  Utils.insertCss(".nextBtn",{
   右:"8px"
  })
  Utils.insertCss(".iconListCont",{
   幅:Zoom.small_width-30*2+"px",
   高さ:"58px",
   位置:"相対",
   左:"30px",
   オーバーフロー:"非表示"
  })
  IconList.gap=((Zoom.small_width-30*2)-(54+4)*IconList.num)/IconList.num;
  Utils.insertCss(".iconList",{
   幅:(54+4+IconList.gap)*list.length+"px",
   リストスタイル:"なし",
   パディング:"0px",
   マージン:"0px",
   位置:"絶対",
   左:"0px",
   上:"0px",
   遷移:"すべて .3"
  })
  Utils.insertCss(".iconList li",{
   フロート:"左",
   幅:"54px",
   高さ:"54px",
   マージン:"0px "+IconList.gap/2+"px",
   カーソル:"ポインタ",
   border:"2px 実線透明"
  })
  Utils.insertCss(".iconList li.active",{
   境界線の色:"#f00"
  })
  Utils.insertCss(".iconList li>img",{
   幅:"54px",
   高さ:"54px"
  })
  Utils.insertCss(".clearfix::after",{
   コンテンツ:"\"。\""、
   表示:"ブロック",
   高さ:"0px",
   クリア:"両方",
   オーバーフロー:"非表示",
   可視性:"非表示"
  })
 }
}

Utils.js ファイルはツールキットです:

デフォルトクラス Utils をエクスポートする{
 静的createE(要素、スタイル、準備){
  要素 = document.createElement(要素);
  if(style) for(let prop in style) elem.style[prop]=style[prop];
  if(prep) for(let prop in prep) elem[prop]=prep[prop];
  要素を返します。
 }
 静的appendTo(要素、親){
  parent.constructor === String の場合、parent = document.querySelector(parent);
  親要素に子要素を追加します。
 }
 静的挿入前(要素、親){
  親コンストラクタが文字列の場合、親は document.querySelector(parent);
  親要素の前に挿入します。
 }
 静的ランダム数(最小値,最大値){
  Math.floor(Math.random*(max-min)+min) を返します。
 }
 静的ランダムカラー(アルファ){
  アルファ=アルファ||Math.random().toFixed(1);
  isNaN(alpha)の場合、alpha=1;
  アルファ>1の場合、アルファ=1;
  アルファ<0の場合、アルファ=0;
  col="rgba("; とします。
  (i=0;i<3;i++) の場合{
   col+=Utils.randomNum(0,256)+",";
  }
  col+=alpha+")";
  列を返します。
 }
 静的挿入Css(選択、スタイル){
  document.styleSheets.length===0の場合{
   styleS = Utils.createE("style"); とします。
   Utils.appendTo(styleS,document.head);
  }
  styleSheet を document.styleSheets[document.styleSheets.length-1] とします。
  str=select+"{"とします。
  for(var prop in スタイル){
   str+=prop.replace(/[AZ]/g,function(item){
    "-"+item.toLocaleLowerCase() を返します。
   })+":"+styles[prop]+";";
  }
  str+="}"
  styleSheet.insertRule(str、styleSheet.cssRules.length);
 }
 静的 getIdElem(要素,obj){
  if(elem.id) obj[elem.id]=elem;
  if(elem.children.length===0) の場合、obj を返します。
  for(let i=0;i<elem.children.length;i++){
   Utils.getIdElem(elem.children[i],obj);
  }
 }
 静的addClass(要素、クラス名){
  arr=(elem.className+" "+className).match(/\S+/g);とします。
  arr = arr.filter((item,index)=>arr.indexOf(item,index+1)<0)
  elem.className=arr.join(" ");
 }
 静的removeClass(要素、クラス名){
  if(!elem.className) 戻り値:
  arr = elem.className.match(/\S+/g); とします。
  arr1=className.match(/\S+/g);とします。
  arr1.forEach(item=>{
   arr = arr.filter(t=>t!==item)
  })
  elem.className=arr.join(" ");
 }
 静的hasClass(要素、クラス名){
  if(!elem.className) は false を返します。
  arr = elem.className.match(/\S+/g); とします。
  arr1=className.match(/\S+/g);とします。
  解決しましょう;
  arr1.forEach(item=>{
   res = arr.some(it=>it===item)
  })
  res を返します。
 }
 静的ロードImg({リスト、ベースパス、コールバック}){
  if(!list || list.length===0) 戻り値:
  if(basePath) list=list.map(item=>basePath+item);
  img = Utils.createE("img"); とします。
  画像データ={
   リスト:リスト、
   コールバック:コールバック、
   結果リスト:[],
   番号:0
  }
  img.addEventListener("load",Utils.loadImgHandler);
  img.src=リスト[img.data.num];
 }
 静的loadImgHandler(e){
  data=e.currentTarget.data とします。
  data.resultList.push(e.currentTarget.cloneNode(false));
  データ.num++;
  if(data.num>data.list.length-1){
   e.currentTarget.removeEventListener("load",Utils.loadImgHandler);
   データコールバック(データ結果リスト);
   データ=null;
   戻る;
  }
  e.currentTarget.src=data.list[データ番号];
 }
}

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

以下もご興味があるかもしれません:
  • JavaScript は、シンプルな虫眼鏡の最も完全なコード分析を実装します (ES5)
  • jsを使用してシンプルな虫眼鏡効果を実現します
  • jsはショッピングサイトの虫眼鏡機能を実現します
  • js を使ってシンプルな虫眼鏡効果を実現
  • js 虫眼鏡拡大画像効果
  • 虫眼鏡の効果を実現するために js を使用する簡単な例
  • 魔法のJavascript画像拡大鏡
  • ネイティブ js で記述された虫眼鏡効果
  • 虫眼鏡アイコンを使用した画像拡大鏡 jquery.jqzoom.js の使用例
  • 画像拡大鏡効果のJSバージョン

<<:  設定ファイルを書いてMyBatisを簡単に使う方法

>>:  Windows Server 2008 R2 マルチユーザー リモート デスクトップ接続ライセンス

推薦する

mysql のインデックスと FROM_UNIXTIME に関する問題

ゼロ、背景今週の木曜日にたくさんのアラートを受け取りました。DBA に確認を依頼したところ、遅いクエ...

MySQL インデックスの詳細な説明

目次1. インデックスの基本1.1 はじめに1.2 インデックスの仕組み1.3 インデックスの種類1...

Vuexの役割についての深い理解

目次概要コンポーネント間でデータを共有する方法Vuex の原則の紹介Vuexはコンポーネントのグロー...

Linux にバイナリ MySQL をインストールして MySQL パスワードをクラックする方法

1. システムに必要な libaio ソフトウェアがインストールされていることを確認します。インスト...

Mysqlはブール型の演算を設定します

Mysqlはブール型を設定します1. Tinyintタイプテストテーブルを作成し、blフィールドをブ...

Docker クロスサーバー通信オーバーレイソリューション (パート 1) Consul 単一インスタンス

目次シナリオタスクアイデア分析するコンセプトと選択ちょっとしたテスト環境説明予防実践テスト引用シナリ...

MySQL における UNION と UNION ALL の基本的な使い方

データベースでは、UNION キーワードと UNION ALL キーワードの両方が 2 つの結果セッ...

大量のデータを含むエレメントのシャトルボックスで「すべて選択」をクリックするとスタックする問題の解決方法

目次解決策1: EUIの転送コンポーネントをコピーして変更し、プロジェクトディレクトリに導入する解決...

JavaScript のマイクロタスクとマクロタスクの説明

序文: js はシングルスレッド言語なので、非同期にすることは不可能です。しかし、js のホスト環境...

JavaScriptオブジェクト指向について学ぼう

目次JavaScript プロトタイプチェーンオブジェクトプロトタイプトップレベルのプロトタイプOb...

vue3 における vuex と pinia の落とし穴

目次導入インストールと使用方法文章の相違点と類似点の簡単な比較VuexとPiniaの長所と短所Pin...

Explainキーワードに基づいてMySQLインデックス機能を最適化する方法

EXPLAIN は、MySQL がインデックスを使用して選択ステートメントを処理し、テーブルを結合す...

Node.jsはブレークポイント再開を実装する

目次ソリューション分析スライス履歴書のダウンロード具体的な解決プロセス論理的分析フロントエンドサーバ...

複数の画像を切り替えるJavaScript

この記事では、複数の画像を切り替えるJavaScriptの具体的なコードを参考までに紹介します。具体...

MySQLクエリ条件のnot inとinの違いと理由

まずSQLを書く SELECT DISTINCT from_id タラから cod.from_id ...