一、引言

在商城的详情页中,放大镜的功能是很常见的。这里京东详情页就要做一个仿放大镜的效果,预览如下:

二、实现原理

实际上,放大镜的实现是单纯用几个div,鼠标移入其中一个小图div,触发事件显示另一个div中的大图。

并非真的使用了某种flash或插件之类,用到放大的效果。所以,网页中的放大镜功能都是模拟。

1、移动功能

小坑:ul有left ,左边距不为0,有20px的间距,所以,应到的位置要加20px作为抵消。

const  LiWIDTH=62;//li的宽
const OFFSET=20;//ul的起始left

注意:在程序中,尽量不要把数值写死,万一后面再改需求的时候,要改变数值,就不方便了。

  • 当li总个数 - moved左移的li个数 =  5时,后面的backward按钮禁用

  • 当moved左移的个数 = 0时,前面的forward按钮禁用
    var LICOUNT = document.querySelectorAll(
"#icon_List>li"
).length;//所有li的个数
var moved = 0;//左移的li个数
var aForward=document.querySelector("a.forward");
var aBackward=document.querySelector("a.backward");
aForward.addEventListener("click", li_move);
aBackward.addEventListener("click", li_move);
function li_move(){
//this->a
//如果当前a的class中没有disabled
if(this.className.lastIndexOf("disabled")==-1){
if(this.className=="forward"){
moved++;
}else{
moved--;
}
//设置ul的left为-LIWIDTH*moved+OFFSET
this.parentNode.lastElementChild.style
.left=-LIWIDTH*moved+OFFSET+"px";
checkA()
}
}
//检查两个a的状态
function checkA(){
if(moved==0){
aBackward.className+=" disabled"//因为是加className 所以disable前要有空格
}else if(LICOUNT-moved==5){
aForward.className+=" disabled"
}else{
aBackward.className="backward";
aForward.className="forward";
}
}

以上:实现小图预览列表的“移动”功能。

2、大图变换

小坑:和小图对应一样的大图显示

规律:大图和小图的图片命名基本一样,唯一不同的地方——大图多加一个“-m”。

解决方法:获得小图的img的src,在后面加“-m”,把新路径设置给大图的mImg的src中。

小坑:小图预览列表有8个,如果每一个都要加“鼠标移入/移出”事件,太繁琐。

解决方法:把事件“鼠标移入/移出”绑定给整个ul,但触发的区域,要设置为img,只有目标元素是img时,才能执行事件。

var mImg=document.getElementById("mImg");
//为id为icon_list的ul绑定鼠标进入事件: document.getElementById("icon_list").addEventListener("mouseover",
function(e){
if(e.target.nodeName=="IMG"){
var src= e.target.src;//获得当前小图片src
var i=src.lastIndexOf(".");//获得最后一个.的位置
src=src.slice(0,i)+"-m"+src.slice(i); //在最后一个.前拼-m
mImg.src=src;//设置mImg的src为src
}
}
)

3、透明遮罩

小坑:mask为小的半透明遮罩,superMask是为了分担img元素事件处理负担的一个辅助div。

原因:因为img的负担很重,它要把图片下载下来,要一点一点的画出来,已经很有负担。之后,在触发事件mousemove时,还要用到它,而且极其的频繁。哪怕移动到一个很小的地方,也会触发这个mousemove事件,这么频繁的触发,这个事件处理它处理不了。结果,就是会导致很卡,img元素反应不过来。

解决方法:在img上面套一个和img一样大的div。这样做的好处是,看着也是在图片上移动,但superMask帮img分担了事件处理这份工作。所以之后的所有事件都要绑定在superMask身上,而不要绑定在img身上。(事件:鼠标移入/移出/移动)

大坑:遮罩如果不限制移动范围,会超出指定大图显示区域。

解决方法:top,left在计算完成之后,不能马上设置,还要做一点加工。设置移动的最大范围值MAX,当top或left计算值小于0时,设为0,大于MAX时,设为MAX。

const MSIZE=175;//mask的大小
const SMSIZE=350;//superMask的大小
//获得id为superMask的div
var sm=document.getElementById("superMask");
var mask=document.getElementById("mask");
sm.addEventListener("mouseover",
function(){
mask.style.display="block";
}
);
sm.addEventListener("mouseout",
function(){
mask.style.display="";
}
);
var MAX=SMSIZE-MSIZE;
//为sm绑定鼠标移动事件
sm.addEventListener("mousemove",
function(e){
var x= e.offsetX,
y= e.offsetY;
var top=y-MSIZE/ 2,
left=x-MSIZE/2;
if(top<0) top=0;
else if(top>MAX) top=MAX;
if(left<0) left=0;
else if(left>MAX) left=MAX;
mask.style.cssText="display:block; left:"+left+"px; top:"+top+"px";
}
)

4、放大镜

div显示图片的原理:背景图片,设置src,和前面一样,获得mImg的src,把后面的“-m”改为“-l”,新路径设置成div的背景图片。

var lgDiv=document.getElementById("largeDiv");
sm.addEventListener("mouseover",
function(){
mask.style.display="block";
lgDiv.style.display="block";
var src=mImg.src;
var i=src.lastIndexOf(".");
src=src.slice(0,i-1)+"l"+src.slice(i);
lgDiv.style.backgroundImage="url("+src+")";
}
);
sm.addEventListener("mouseout",
function(){
mask.style.display="";
lgDiv.style.display="";
}
);
var MAX=SMSIZE-MSIZE;
sm.addEventListener("mousemove",
function(e){
var x= e.offsetX,
y= e.offsetY;
var top=y-MSIZE/ 2,
left=x-MSIZE/2;
if(top<0) top=0;
else if(top>MAX) top=MAX;
if(left<0) left=0;
else if(left>MAX) left=MAX;
mask.style.cssText="display:block; left:"+left+"px; top:"+top+"px";
lgDiv.style.backgroundPosition=-left*2+"px "+ -top*2+"px";
}
)

注:转载请注明出处

【京东详情页】——原生js爬坑之放大镜的更多相关文章

  1. 【京东详情页】——原生js爬坑之二级菜单

    一.引言 做京东详情页仿写的时候,要用原生js实现顶部菜单的二级菜单显示与隐藏事件的触发. 过程中遇到了一个坑,在这里与大家分享.要实现的效果如下: 二.坑 谁触发事件?显示.隐藏二级菜单       ...

  2. 【京东详情页】——原生js爬坑之标签页

    一.引言 要做详情页的商品评价等5个li的标签页转换,效果如下: 二.实现原理 有一个特别的地方:上面五个li,但下面只有四个容器(table/div). 设计的目的:无论点哪个li,只有前四个div ...

  3. 【2048小游戏】——原生js爬坑之封装行的移动算法&事件

    引言:2048小游戏的核心玩法是移动行,包括横行和纵行,玩家可以选择4个方向,然后所有行内的数字就会随着行的移动而向特定的方向移动.这个行的移动是一个需要重复调用的算法,所以这里就要将一行的移动算法封 ...

  4. 【2048小游戏】——原生js爬坑之遍历算法显示二维数组内容

    引言:做2048小游戏会将横纵方向的数字内容,存储在一个二维数组中,要将这个二维数组中的内容显示在页面上,就一定要用遍历算法来实现了. 一.二维数组存储    首先考虑用二维数组存储所有行数,列数   ...

  5. 【2048小游戏】——CSS/原生js爬坑之纯CSS模态对话框&游戏结束

    引言:2048小游戏的结束界面,使用纯CSS制作模态对话框,一般做模态对话框都会使用BootStrap自带的模态对话框组件方便使用,但在制作要运行在移动端的小项目时,就不能使用BootStrap,因为 ...

  6. 【京东详情页】——原生js学习之匿名函数

    一.引言 在js模块中,要给每一个功能封装一个匿名函数.为了更好的理解什么是匿名函数,为什么要用匿名函数,我做了一些查阅和学习. 二.匿名函数 什么是:在创建时,不被任何变量引用的函数. 为什么:节约 ...

  7. H5-移动端实现滑屏翻页-原生js/jquery

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Jmeter使用Websocket插件测试SingalR,外加还有阿里云PTS的Jmeter原生测试爬坑日志。

    题外话:距离我的上一篇博客已经过去7年多了,我实在是个不务正业的程序员,遇到测试方面的东西总想分享一下,因为可用的资料实在太少了(包括国外的资料). 本人不喜欢授人以鱼,所以不会直接给出问题和解决方案 ...

  9. 原生js实现简单的放大镜效果

    前言:相信很多同学在浏览购物网站的时候都会用到过放大镜的功能,这个功能在日常的网站也会经常用到.接下来我们开始实现一下它吧: (1)首先了解一下放大镜效果的html架构:如下图,它由两部分组成. ht ...

随机推荐

  1. 记一次被yield return坑的历程。

    事情的经过是这样的: 我用C#写了一个很简单的一个通过迭代生成序列的函数. public static IEnumerable<T> Iterate<T>(this Func& ...

  2. UIGraphicsBeginImageContext - 位图上下文

    UIGraphicsBeginImageContext 首先,先来认识一个UIGraphicsBeginImageContext,它会创建一个基于位图的上下文(context)(默认创建一个透明的位图 ...

  3. ASP.Net Core Razor 页面路由

    在服务器端 Web 应用程序框架中,其中非常重要的设计是开发人员如何将URL与服务器上的资源进行匹配,以便正确的处理请求.最简单的方法是将 URL 映射到磁盘上的物理文件,在 Razor 页面框架中, ...

  4. 大手册(书籍)排版利器-XML自动排版生成工具

    --支持全球化/多语言/符合W3C标准的XML自动排版工具 Boxth XML/XSL Formatter是专为XML数据或其他结构化数据源自动输出排版文件(如: PDF等)而设计的集数据格式化.版式 ...

  5. CentOS7.3虚拟机扩展数据磁盘

    操作之前需要重点查看: 由于扩容磁盘的操作非同小可,一旦哪一步出现问题,就会导致分区损坏,数据丢失等一系列严重的问题,因此建议:在进行虚拟机分区扩容之前,一定要备份重要数据文件,并且先在测试机上验证以 ...

  6. 帆软的报表系统与泛微OA结合起来,这两个软件麦枫提供了经典的服务。

    一.集成配景泛微OA对企业的代价 泛微协同办公计划能向你供给一个协同的.集成的办公情况,使所有的办公职员都在统一且个性化的信息流派中一路事情, 解脱光阴和地区的限定,实现协同事情与知识治理. Eoco ...

  7. 两台主机之间单向Ping不通的问题

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px ".PingFang SC"; color: #454545 } p.p2 ...

  8. geotrellis使用(三十二)大量GeoTiff文件实时进行TMS服务

    前言 在上一篇文章中我讲了如何直接将Geotiff文件发布为TMS服务,在其中只讲了单幅Geotiff的操作,其实单幅这种量级的数据对Geotrellis来说就是杀鸡焉用牛刀,Geotrellis针对 ...

  9. WebForm页面间传值方法(转)

    Asp.NET WEB FORMS 给开发者提供了极好的事件驱动开发模式.Asp .NET为我们提供了三种方式,一种是可以通过用QueryString来传送相应的值,再一种是通过session变量来传 ...

  10. 第2阶段——编写uboot之启动内核和制作Makefile(2)

    目标: 1   添加头文件setup.h和serial.h 2   写main函数   2.1 帮内核设置串口0, (内核启动会打印出启动信息) 2.2把内核读入到SDRAM 2.3设置参数(参考u- ...