本文实例为大家分享了js实现放大镜组件开发的具体代码,供大家参考,具体内容如下
功能需求:
1、根据图片数组创建图标列表;
2、鼠标滑过图标时,当前图标增加红色边框;
3、鼠标滑过图标时,上方图片区域显示对应的图片,右侧显示放大后的图片内容;
4、鼠标在图片区域移动时,在右侧实现放大效果;
5、下方图标列表,点击左右按钮,实现翻页效果;
6、当图标内容不够一页时,只移动到最后一个图标的位置;
以京东的详情页为例,看一下效果:
放大镜内容写在 Zoom.js 文件里,下方的图标列表内容写在 IconList.js 文件里,当鼠标滑过下面的图标时,需要更改放大镜里div的背景图片,这里用到了事件抛发。
下面附上代码:
html结构 :
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'; //图标数组 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文件,创建放大镜组件:
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); //创建外层的div容器 this .elem= this .createE(); //监听事件,改变zoomSmall的背景图 document.addEventListener(Zoom.SET_BG_IMG,e=> this .setBgImg(e)); //创建下方的icon列表 this .createIconList(_list, this .elem); } createE(){ //创建外层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)); return div; } appendTo(parent){ Utils.appendTo( this .elem,parent); } setBgImg(e){ //设置背景图片 this .zoomSmall.style.backgroundImage=`url(${e.src})`; this .zoomCont.style.backgroundImage=`url(${e.src})`; } createIconList(list,parent){ //创建下方icon图标列表 let iconList= new IconList(list); Utils.appendTo(iconList.elem,parent); } mouseHandler(e){ switch (e.type) { case "mouseenter" : //鼠标滑入后,显示遮罩和右侧大图片 this .zoomMask.style.display= "block" ; this .zoomCont.style.display= "block" ; //监听鼠标移动和滑出事件 this .mouseHandlers=e=> this .mouseHandler(e); this .zoomSmall.addEventListener( "mousemove" , this .mouseHandlers); this .zoomSmall.addEventListener( "mouseleave" , this .mouseHandlers); break ; case "mousemove" : //遮罩移动 this .zoomMaskMove(e); break ; case "mouseleave" : //鼠标滑出后,显示遮罩和右侧大图片 this .zoomMask.style.display= "none" ; this .zoomCont.style.display= "none" ; //移除鼠标移动和滑出事件 this .zoomSmall.removeEventListener( "mousemove" , this .mouseHandlers); this .zoomSmall.removeEventListener( "mouseleave" , this .mouseHandlers); break ; } } zoomMaskMove(e){ //遮罩移动 let rect= this .elem.getBoundingClientRect(); //计算let和top的值,等于鼠标的坐标-父容器的left值-遮罩的一半宽 let x=e.clientX-rect.x-Zoom.mask_width/2; let y=e.clientY-rect.y-Zoom.mask_width/2; //判断left和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" ; //大图片移动 this .zoomContMove(x,y); } zoomContMove(_x,_y){ //计算大图片的背景定位,公式:zoom的宽/mask的宽=zoom的背景left值/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(){ //设置样式 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文件,创建下方图标列表,并完成翻页效果:
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; //每页显示的图标数 static gap=0; //表示li的左右间距 position=0; //当前显示的图标为第几页 x=0; //列表的left值 prepIcon; //上一个点击的图标 static SET_BG_IMG= "set_bg_img" ; constructor(list){ this .list=list; this .elem= this .createE(); } createE(){ //创建外层容器 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" >`; //设置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); return div; } createIcon(){ //创建图标列表 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; //如果点击的不是左右按钮,直接跳出 if (!/prev/.test(src)&&!/next/.test(src)) return ; //每一个li的实际宽度,width+border+margin let liWidth=54+4+IconList.gap; //page为一共有几个整数页 let page=Math.floor( this .list.length/IconList.num)-1; //remainder为最后不够一页的剩余图标数 let remainder= this .list.length%IconList.num; if (/prev/.test(src)){ //如果点击的是上一页按钮 if ( this .x===0) return ; //移动到最后一页时 if ( this .position===0&&remainder>0){ //移动的距离加等于li宽度*剩余图标数 this .x+=liWidth*remainder; } else if ( this .position<=page){ this .position--; //移动的距离加等于li的宽度*每页显示的图标数(5个) this .x+=liWidth*IconList.num; } } else if (/next/.test(src)){ //如果点击的是下一页按钮 if ( this .x===-( this .list.length-IconList.num)*liWidth) return ; if ( this .position===page&&remainder>0){ //移动的距离减等于li宽度*剩余图标数 this .x-=liWidth*remainder; } else if ( this .position<page){ this .position++; //移动的距离减等于li的宽度*每页显示的图标数(5个) this .x-=liWidth*IconList.num; } } //设置图标列表的left值 this .iconList.style.left= this .x+ "px" ; } mouseHandler(e){ //如果滑过的不是Img标签,直接跳出 if (e.target.constructor!==HTMLImageElement) return ; //设置背景图片 this .setBgImg(e.target); //设置当前滑过图标的样式 this .setIconState(e.target.parentElement); } setIconState(target){ //移除上一个滑过图标的active样式 if ( this .prepIcon) Utils.removeClass( this .prepIcon, "active" ); //将当前滑过的对象赋值给this.prepIcon this .prepIcon=target; //给当前滑过图标增加active样式 Utils.addClass( this .prepIcon, "active" ); } setBgImg(target){ //抛发事件,将当前图片的src传过去 let src=target.src.replace( "_icon" , "" ); let evt= new Event(IconList.SET_BG_IMG); evt.src=src; document.dispatchEvent(evt); } static setStyles(list){ //设置样式 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文件,是一个工具包:
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]; } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。
- 本文固定链接: https://zxbcw.cn/post/204545/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)