一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

node.js|vue.js|jquery|angularjs|React|json|js教程|

服務(wù)器之家 - 編程語言 - JavaScript - js教程 - 原生js實(shí)現(xiàn)放大鏡組件

原生js實(shí)現(xiàn)放大鏡組件

2022-01-06 15:08蒲公英芽 js教程

這篇文章主要為大家詳細(xì)介紹了js實(shí)現(xiàn)放大鏡組件,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了js實(shí)現(xiàn)放大鏡組件開發(fā)的具體代碼,供大家參考,具體內(nèi)容如下

功能需求:

1、根據(jù)圖片數(shù)組創(chuàng)建圖標(biāo)列表;
2、鼠標(biāo)滑過圖標(biāo)時(shí),當(dāng)前圖標(biāo)增加紅色邊框;
3、鼠標(biāo)滑過圖標(biāo)時(shí),上方圖片區(qū)域顯示對(duì)應(yīng)的圖片,右側(cè)顯示放大后的圖片內(nèi)容;
4、鼠標(biāo)在圖片區(qū)域移動(dòng)時(shí),在右側(cè)實(shí)現(xiàn)放大效果;
5、下方圖標(biāo)列表,點(diǎn)擊左右按鈕,實(shí)現(xiàn)翻頁效果;
6、當(dāng)圖標(biāo)內(nèi)容不夠一頁時(shí),只移動(dòng)到最后一個(gè)圖標(biāo)的位置;

以京東的詳情頁為例,看一下效果:

原生js實(shí)現(xiàn)放大鏡組件

放大鏡內(nèi)容寫在 Zoom.js 文件里,下方的圖標(biāo)列表內(nèi)容寫在 IconList.js 文件里,當(dāng)鼠標(biāo)滑過下面的圖標(biāo)時(shí),需要更改放大鏡里div的背景圖片,這里用到了事件拋發(fā)。

下面附上代碼:

html結(jié)構(gòu) :

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>zoom</title>
</head>
<body>
 <script type="module">
  import Zoom from './js/Zoom.js';
  //圖標(biāo)數(shù)組
  let list=["a_icon.jpg","e_icon.jpg","f_icon.jpg","g_icon.jpg","h_icon.jpg","i_icon.jpg","j_icon.jpg",];
  init();
  function init(){
   let zoom=new Zoom(list,"./img/");
   zoom.appendTo("body");
  }
 </script>
</body>
</html>

Zoom.js文件,創(chuàng)建放大鏡組件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import Utils from "./Utils.js";
import IconList from './IconList.js';
export default class Zoom{
 static styles=false;
 static small_width=450;
 static mask_width=303.75;
 static zoom_width=540;
 static SET_BG_IMG="set_bg_img";
 constructor(_list,_basePath){
  if(_basePath) _list=_list.map(item=>_basePath+item);
  //創(chuàng)建外層的div容器
  this.elem=this.createE();
  //監(jiān)聽事件,改變zoomSmall的背景圖
  document.addEventListener(Zoom.SET_BG_IMG,e=>this.setBgImg(e));
  //創(chuàng)建下方的icon列表
  this.createIconList(_list,this.elem);
 }
 createE(){
  //創(chuàng)建外層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>`;
  //設(shè)置樣式
  Zoom.setStyle();
  //獲取樣式
  Utils.getIdElem(div,this);
  //監(jiān)聽鼠標(biāo)滑入事件
  this.zoomSmall.addEventListener("mouseenter",e=>this.mouseHandler(e));
  return div;
 }
 appendTo(parent){
  Utils.appendTo(this.elem,parent);
 }
 setBgImg(e){
  //設(shè)置背景圖片
  this.zoomSmall.style.backgroundImage=`url(${e.src})`;
  this.zoomCont.style.backgroundImage=`url(${e.src})`;
 }
 createIconList(list,parent){
  //創(chuàng)建下方icon圖標(biāo)列表
  let iconList=new IconList(list);
  Utils.appendTo(iconList.elem,parent);
 }
 mouseHandler(e){
  switch (e.type) {
   case "mouseenter":
    //鼠標(biāo)滑入后,顯示遮罩和右側(cè)大圖片
    this.zoomMask.style.display="block";
    this.zoomCont.style.display="block";
    //監(jiān)聽鼠標(biāo)移動(dòng)和滑出事件
    this.mouseHandlers=e=>this.mouseHandler(e);
    this.zoomSmall.addEventListener("mousemove",this.mouseHandlers);
    this.zoomSmall.addEventListener("mouseleave",this.mouseHandlers);
    break;
   case "mousemove":
    //遮罩移動(dòng)
    this.zoomMaskMove(e);
    break;
   case "mouseleave":
    //鼠標(biāo)滑出后,顯示遮罩和右側(cè)大圖片
    this.zoomMask.style.display="none";
    this.zoomCont.style.display="none";
    //移除鼠標(biāo)移動(dòng)和滑出事件
    this.zoomSmall.removeEventListener("mousemove",this.mouseHandlers);
    this.zoomSmall.removeEventListener("mouseleave",this.mouseHandlers);
    break;
  }
 }
 zoomMaskMove(e){
  //遮罩移動(dòng)
  let rect=this.elem.getBoundingClientRect();
  //計(jì)算let和top的值,等于鼠標(biāo)的坐標(biāo)-父容器的left值-遮罩的一半寬
  let x=e.clientX-rect.x-Zoom.mask_width/2;
  let y=e.clientY-rect.y-Zoom.mask_width/2;
  //判斷l(xiāng)eft和top的范圍
  if(x<0) x=0;
  if(x>Zoom.small_width-Zoom.mask_width) x=Zoom.small_width-Zoom.mask_width;
  if(y<0) y=0;
  if(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";
  //大圖片移動(dòng)
  this.zoomContMove(x,y);
 }
 zoomContMove(_x,_y){
  //計(jì)算大圖片的背景定位,公式:zoom的寬/mask的寬=zoom的背景l(fā)eft值/mask的left值
  let x=-Zoom.zoom_width/Zoom.mask_width*_x;
  let y=-Zoom.zoom_width/Zoom.mask_width*_y;
  this.zoomCont.style.backgroundPosition=x+"px "+y+"px";
 }
 static setStyle(){
  //設(shè)置樣式
  if(Zoom.styles) return;
  Zoom.styles=true;
  Utils.insertCss(".zoomContainer",{
   width:Zoom.small_width+"px",
   height:Zoom.small_width+"px",
   position:"relative"
  })
  Utils.insertCss(".zoomSmall",{
   width:Zoom.small_width+"px",
   height:Zoom.small_width+"px",
   border: "1px solid #000",
   backgroundSize: "100% 100%",
   position:"absolute",
   left:"0px",
   top:"0px"
  })
  Utils.insertCss(".zoomMask",{
   width: this.mask_width + "px",
   height: this.mask_width + "px",
   backgroundColor: "rgba(200,170,0,0.3)",
   position: "absolute",
   left: "0px",
   top: "0px",
   display: "none"
  })
  Utils.insertCss(".zoomContent",{
   width: this.zoom_width + "px",
   height: this.zoom_width + "px",
   border: "1px solid #ccc",
   position: "absolute",
   left: (this.small_width + 2) + "px",
   top: "0px",
   display: "none"
  })
 }
}

IconList.js文件,創(chuàng)建下方圖標(biāo)列表,并完成翻頁效果:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import Utils from "./Utils.js";
import Zoom from "./Zoom.js";
export default class IconList{
 static styles=false;
 static num=5;//每頁顯示的圖標(biāo)數(shù)
 static gap=0;//表示li的左右間距
 position=0;//當(dāng)前顯示的圖標(biāo)為第幾頁
 x=0;//列表的left值
 prepIcon;//上一個(gè)點(diǎn)擊的圖標(biāo)
 static SET_BG_IMG="set_bg_img";
 constructor(list){
  this.list=list;
  this.elem=this.createE();
 }
 createE(){
  //創(chuàng)建外層容器
  let div=Utils.createE("div");
  div.className="iconContainer";
  div.innerHTML=`<img class="prevBtn" src="./img/prev.png"><div class="iconListCont">${this.createIcon()}</div><img class="nextBtn" src="./img/next.png">`;
  //設(shè)置css樣式
  IconList.setStyles(this.list);
  //獲取元素
  Utils.getIdElem(div,this);
  //外層容器監(jiān)聽點(diǎn)擊事件
  div.addEventListener("click",e=>this.clickHandler(e));
  //圖標(biāo)列表監(jiān)聽鼠標(biāo)滑過事件
  this.iconList.addEventListener("mouseover",e=>this.mouseHandler(e));
  //默認(rèn)顯示第一個(gè)圖標(biāo)的邊框
  this.setIconState(this.iconList.firstElementChild);
  //默認(rèn)顯示第一個(gè)圖片
  this.setBgImg(this.iconList.firstElementChild.firstElementChild);
  return div;
 }
 createIcon(){
  //創(chuàng)建圖標(biāo)列表
  let str=`<ul class="iconList clearfix" id="iconList">`;
  this.list.forEach(item=>{
   str+=`<li><img src="${item}"></li>`;
  })
  str+="</ul>";
  return str;
 }
 clickHandler(e){
  let src=e.target.src;
  //如果點(diǎn)擊的不是左右按鈕,直接跳出
  if(!/prev/.test(src)&&!/next/.test(src)) return;
  //每一個(gè)li的實(shí)際寬度,width+border+margin
  let liWidth=54+4+IconList.gap;
  //page為一共有幾個(gè)整數(shù)頁
  let page=Math.floor(this.list.length/IconList.num)-1;
  //remainder為最后不夠一頁的剩余圖標(biāo)數(shù)
  let remainder=this.list.length%IconList.num;
  if(/prev/.test(src)){
   //如果點(diǎn)擊的是上一頁按鈕
   if(this.x===0) return;
   //移動(dòng)到最后一頁時(shí)
   if(this.position===0&&remainder>0){
    //移動(dòng)的距離加等于li寬度*剩余圖標(biāo)數(shù)
    this.x+=liWidth*remainder;
   }
   else if(this.position<=page){
    this.position--;
    //移動(dòng)的距離加等于li的寬度*每頁顯示的圖標(biāo)數(shù)(5個(gè))
    this.x+=liWidth*IconList.num;
   }
  }else if(/next/.test(src)){
   //如果點(diǎn)擊的是下一頁按鈕
   if(this.x===-(this.list.length-IconList.num)*liWidth) return;
   if(this.position===page&&remainder>0){
    //移動(dòng)的距離減等于li寬度*剩余圖標(biāo)數(shù)
    this.x-=liWidth*remainder;
   }
   else if(this.position<page){
    this.position++;
    //移動(dòng)的距離減等于li的寬度*每頁顯示的圖標(biāo)數(shù)(5個(gè))
    this.x-=liWidth*IconList.num;
   }
  }
  //設(shè)置圖標(biāo)列表的left值
  this.iconList.style.left=this.x+"px";
 }
 mouseHandler(e){
  //如果滑過的不是Img標(biāo)簽,直接跳出
  if(e.target.constructor!==HTMLImageElement) return;
  //設(shè)置背景圖片
  this.setBgImg(e.target);
  //設(shè)置當(dāng)前滑過圖標(biāo)的樣式
  this.setIconState(e.target.parentElement);
 }
 setIconState(target){
  //移除上一個(gè)滑過圖標(biāo)的active樣式
  if(this.prepIcon) Utils.removeClass(this.prepIcon,"active");
  //將當(dāng)前滑過的對(duì)象賦值給this.prepIcon
  this.prepIcon=target;
  //給當(dāng)前滑過圖標(biāo)增加active樣式
  Utils.addClass(this.prepIcon,"active");
 }
 setBgImg(target){
  //拋發(fā)事件,將當(dāng)前圖片的src傳過去
  let src=target.src.replace("_icon","");
  let evt=new Event(IconList.SET_BG_IMG);
  evt.src=src;
  document.dispatchEvent(evt);
 }
 static setStyles(list){
  //設(shè)置樣式
  if(IconList.styles) return;
  IconList.styles=true;
  Utils.insertCss(".iconContainer",{
   width:Zoom.small_width+2+"px",
   height: "58px",
   position: "absolute",
   top: Zoom.small_width+2+"px",
   left: "0px",
  })
  Utils.insertCss(".iconContainer>img",{
   width:"22px",
   height:"32px",
   cursor:"pointer",
   position:"absolute",
   top:"13px",
  })
  Utils.insertCss(".prevBtn",{
   left:"8px"
  })
  Utils.insertCss(".nextBtn",{
   right:"8px"
  })
  Utils.insertCss(".iconListCont",{
   width:Zoom.small_width-30*2+"px",
   height:"58px",
   position:"relative",
   left:"30px",
   overflow:"hidden"
  })
  IconList.gap=((Zoom.small_width-30*2)-(54+4)*IconList.num)/IconList.num;
  Utils.insertCss(".iconList",{
   width:(54+4+IconList.gap)*list.length+"px",
   listStyle:"none",
   padding:"0px",
   margin:"0px",
   position:"absolute",
   left:"0px",
   top:"0px",
   transition:"all .3s"
  })
  Utils.insertCss(".iconList li",{
   float:"left",
   width:"54px",
   height:"54px",
   margin:"0px "+IconList.gap/2+"px",
   cursor:"pointer",
   border:"2px solid transparent"
  })
  Utils.insertCss(".iconList li.active",{
   borderColor:"#f00"
  })
  Utils.insertCss(".iconList li>img",{
   width:"54px",
   height:"54px"
  })
  Utils.insertCss(".clearfix::after",{
   content:"\".\"",
   display:"block",
   height:"0px",
   clear:"both",
   overflow:"hidden",
   visibility:"hidden"
  })
 }
}

Utils.js文件,是一個(gè)工具包:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
export default class Utils{
 static createE(elem,style,prep){
  elem=document.createElement(elem);
  if(style) for(let prop in style) elem.style[prop]=style[prop];
  if(prep) for(let prop in prep) elem[prop]=prep[prop];
  return elem;
 }
 static appendTo(elem,parent){
  if (parent.constructor === String) parent = document.querySelector(parent);
  parent.appendChild(elem);
 }
 static insertBefore(elem,parent){
  if(parent.constructor === String) parent=document.querySelector(parent);
  parent.insertBefore(elem,parent.firstElementChild);
 }
 static randomNum(min,max){
  return Math.floor(Math.random*(max-min)+min);
 }
 static randomColor(alpha){
  alpha=alpha||Math.random().toFixed(1);
  if(isNaN(alpha)) alpha=1;
  if(alpha>1) alpha=1;
  if(alpha<0) alpha=0;
  let col="rgba(";
  for(let i=0;i<3;i++){
   col+=Utils.randomNum(0,256)+",";
  }
  col+=alpha+")";
  return col;
 }
 static insertCss(select,styles){
  if(document.styleSheets.length===0){
   let styleS=Utils.createE("style");
   Utils.appendTo(styleS,document.head);
  }
  let styleSheet=document.styleSheets[document.styleSheets.length-1];
  let str=select+"{";
  for(var prop in styles){
   str+=prop.replace(/[A-Z]/g,function(item){
    return "-"+item.toLocaleLowerCase();
   })+":"+styles[prop]+";";
  }
  str+="}"
  styleSheet.insertRule(str,styleSheet.cssRules.length);
 }
 static getIdElem(elem,obj){
  if(elem.id) obj[elem.id]=elem;
  if(elem.children.length===0) return obj;
  for(let i=0;i<elem.children.length;i++){
   Utils.getIdElem(elem.children[i],obj);
  }
 }
 static addClass(elem,className){
  let arr=(elem.className+" "+className).match(/\S+/g);
  arr=arr.filter((item,index)=>arr.indexOf(item,index+1)<0)
  elem.className=arr.join(" ");
 }
 static removeClass(elem,className){
  if(!elem.className) return;
  let arr=elem.className.match(/\S+/g);
  let arr1=className.match(/\S+/g);
  arr1.forEach(item=>{
   arr=arr.filter(t=>t!==item)
  })
  elem.className=arr.join(" ");
 }
 static hasClass(elem,className){
  if(!elem.className) return false;
  let arr=elem.className.match(/\S+/g);
  let arr1=className.match(/\S+/g);
  let res;
  arr1.forEach(item=>{
   res= arr.some(it=>it===item)
  })
  return res;
 }
 static loadImg({list,basePath,callback}){
  if(!list || list.length===0) return;
  if(basePath) list=list.map(item=>basePath+item);
  let img=Utils.createE("img");
  img.data={
   list:list,
   callback:callback,
   resultList:[],
   num:0
  }
  img.addEventListener("load",Utils.loadImgHandler);
  img.src=list[img.data.num];
 }
 static loadImgHandler(e){
  let data=e.currentTarget.data;
  data.resultList.push(e.currentTarget.cloneNode(false));
  data.num++;
  if(data.num>data.list.length-1){
   e.currentTarget.removeEventListener("load",Utils.loadImgHandler);
   data.callback(data.resultList);
   data=null;
   return;
  }
  e.currentTarget.src=data.list[data.num];
 }
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/Charissa2017/article/details/104159002

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 欧美国产日韩1区俺去了 | 日韩精品视频在线观看免费 | 日韩成人一区ftp在线播放 | 毛片免费全部免费观看 | 99久久国产综合精麻豆 | 99热这里只有精 | 欧美激情影音先锋 | 痴mu动漫成年动漫在线观看 | 午夜网| 五月天91 | 接吻吃胸摸下面啪啪教程 | 双性np肉文 | 久久艹综合 | 国产精品原创视频 | 俄罗斯一级淫片 | 欧美精品一区二区三区免费 | 欧美成人精品第一区二区三区 | 黄色大片网 | 国产91在线九色 | 国产黄色大片网站 | 国模李丽莎大尺度啪啪 | 免费高清www动漫视频播放器 | 无码AV免费精品一区二区三区 | 四虎综合九九色九九综合色 | 天天爱天天做天天爽天天躁 | 日本妇人成熟免费观看18 | 非洲特级特黄aa大片 | 国产剧情一区二区三区 | 成人在线视频国产 | 好大好想要 | 啪啪无尽3d动漫漫画免费网站 | 精品国产乱码久久久久久免费流畅 | 我把校花黑色蕾丝胸罩脱了 | 无码区国产区在线播放 | 亚洲a视频在线 | 操小女人 | www免费看 | 婷婷丁香色综合狠狠色 | 成年人在线观看免费视频 | 女性性色生活片免费观看 | 午夜视频网站 |