虫眼鏡コンポーネントのネイティブ 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 マルチユーザー リモート デスクトップ接続ライセンス

推薦する

JavaScript データ型変換の例 (他の型を文字列、数値型、ブール型に変換する)

序文データ型変換とは何ですか?フォームまたはプロンプトを使用して取得されるデフォルトのデータ型は文字...

CSS3で実装された3Dトンネル効果

達成された効果実装コードhtml <div class="scene"&g...

MySQL マルチテーブルクエリ例の詳しい解説 [リンククエリ、サブクエリなど]

この記事では、例を挙げて MySQL のマルチテーブル クエリについて説明します。ご参考までに、詳細...

dockerでredis5.0.3をインストールする方法

1. 公式5.0.3イメージを取得する [root@localhost ~]# docker pul...

Vue.js を学ぶ際に遭遇する落とし穴

目次クラス void のポイントES6 矢印関数ヴュートファイvue-cli非同期と同期実行と展開ヒ...

新しい Linux ファイル権限設定における umask の詳細な理解

序文起源は質問 1 です: umask が 022 に設定されている場合、作成するファイルのデフォル...

HTML タグ マーキーはさまざまなスクロール効果を実現します (JS 制御なし)

ページの自動スクロール効果は JavaScript で実現できますが、今日偶然、JS 制御なしでさま...

CSS スタイルの導入方法とその長所と短所の紹介

CSSを導入する3つの方法1. インラインスタイル利点: 書きやすく、重みがある 欠点: 構造とスタ...

CSS でフローティングにより親要素の高さが崩れる問題を解決するいくつかの方法

1. ドキュメントフローとフローティング1. ドキュメントフローとは何ですか? HTML では、ドキ...

Dockerイメージの作成Dockerfileとコミット操作

イメージを構築するイメージを構築するには、主に 2 つの方法があります。実行中のコンテナをイメージに...

MySQLのREDOログ(リドゥログ)とロールバックログ(アンドゥログ)の詳しい説明

序文:前回の記事では、MySQL システムでよく使用されるログをいくつか説明しました。実は、トランザ...

mysqldump を使用した MySql のインポートおよびエクスポート方法の概要

データベースデータをエクスポートします:まずcmdを開いてMySQLのbinフォルダに入ります1. ...

HTML入力ファイルコントロールはアップロードされるファイルの種類を制限します

入力ファイルの HTML コントロールを Web ページに追加します。 <input id=&...

MySQL 5.7.18 インストーラーのインストール ダウンロード グラフィック チュートリアル

この記事では、MySQL 5.7.18インストーラーの詳細なインストールチュートリアルを参考までに記...