效果:

1、  鼠标放上去会有半透明遮罩、右边会有大图片局部图

2、  鼠标移动时右边的大图片也会局部移动

放大镜的关键原理:

鼠标在小图片上移动时,通过捕捉鼠标在小图片上的位置,定位大图片的相应位置;

放大镜的移动方向和大图片的移动方向:横向和纵向都是相反,才可以保证同步;

页面元素:

技术点:事件捕获,定位

难点:计算

需要元素:小图片和大图片,存放小图片和大图片的容器,有一个放大镜;

涉及到的技术点:

(1)       鼠标事件的捕获:onmouseover(进入)、onmouseout(移除)、onmousemove(移动)

(2)       offsetLeft、offsetTop、offsetWidth、offsetHeight、event.clientX、event.clientY

  • offsetLeft子元素相对于父元素的左位移
  • offsetWidth,offsetHeight一个元素的宽度和高度,宽度和高度是不包括滚动条的。

event.clientX、event.clientY鼠标的X轴和Y轴,相对于整个页面的坐标,而不是子元素

  • offsetLeft和style.left对比:

(1)、style.left返回的是字符串,如30px、offsetLeft返回的是数值30;

(2)、style.left是可读写的,offsetLeft是只读的,所以要改变div的位置,只能修改style.left;

(3)、style.left的值需要事先定义,否则取到的值为空。

style.left只针对在HTML中写的值有效,样式表中无法定义style.left;

制作放大镜所需要的计算

》重点:如何让小图片上的放大镜和大图片同步移动

关键:小图片的比例和大图片的比例是一样的,放大镜比例和右侧大的容器比例是一样的;他们之间的比例是相同的

移动时的比例计算:

放大镜核心计算公式:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>放大镜</title>
<style>
* {
margin: 0;
padding: 0
}
#demo {
display: block;
width: 323px;
height: 430px;
margin: 5px;
position: relative;
border: 1px solid #ccc;
}
#small-box {
position: relative;
z-index: 1;
}
#float-box {
display: none;
width: 160px;
height: 120px;
position: absolute;/*使元素脱离文档流,方便自由操控元素*/
background: #ffffcc;
border: 1px solid #ccc;
filter: alpha(opacity=50);
opacity: 0.5;
}
#mark {/*应该是把图片放在这个上面,它的透明度为0,是个block*/
position: absolute; /*元素脱离文档流,使得图片和浮动框可与之重叠,也正因如此,要↓*/
display: block; ↓
width: 323px; ↓                 
height: 430px; ↓
background-color: #fff; ↓
filter: alpha(opacity=0);/*过滤器,目前只有少数浏览器支持*/ ↓
opacity: 0; ↓
z-index: 10;/*确保markBox位于floatBox和图片之上,防止markBox被覆盖,导致对markBox的鼠标移动事件不起作用*/
}
#big-box {
display: none;
position: absolute;
top: 0;
left: 330px;
width: 400px;
height: 300px;
overflow: hidden;
border: 1px solid #ccc;
z-index: 1;
} #big-box img {
position: absolute;
z-index: 5
}
</style>
<script> //页面加载完毕后执行
window.onload = function () {
//找六个个元素:demo,smallBox,foatBox,mark,bigfloatBox,imgs,
var objDemo=document.getElementById("demo");
var objSmallBox=document.getElementById("small-box");
var objMarkBox=document.getElementById("mark");
var objFloatBox=document.getElementById("float-box");
var objBigBox=document.getElementById("big-box");
var objBigBoxImg=objBigBox.getElementsByTagName("img")[0]; //给小盒子添加事件,移入和移出
//移入:浮动的box和和bigBox显示
objSmallBox.onmouseover=function(){
objFloatBox.style.display="block";
objBigBox.style.display="block";
}
//移除:浮动的box和bigBox隐藏
objSmallBox.onmouseout=function(){
objFloatBox.style.display="none";
objBigBox.style.display="none";
} //给小盒子添加鼠标移动事件
objMarkBox.onmousemove=function(ev){
var _event=ev||window.event;//做兼容性,兼容IE
//1计算值:
var left=_event.clientX-objDemo.offsetLeft-objSmallBox.offsetLeft-objFloatBox.offsetWidth/2;
var top=_event.clientY-objDemo.offsetTop-objSmallBox.offsetTop-objFloatBox.offsetHeight/2; //5.优化,在前面加判断,不让其溢出,加判断
if(left<0) left=0;
if(top<0) top=0;
if(left>objSmallBox.offsetWidth-objFloatBox.offsetWidth)
left=objSmallBox.offsetWidth-objFloatBox.offsetWidth;
if(top>objSmallBox.offsetHeight-objFloatBox.offsetHeight)
top=objSmallBox.offsetHeight-objFloatBox.offsetHeight; //2把值赋值给放大镜
objFloatBox.style.left=left+"px";
objFloatBox.style.top=top+"px"; //3计算比例
var percentX=left/(objMarkBox.offsetWidth-objFloatBox.offsetWidth);
var percentY=top/(objMarkBox.offsetHeight-objFloatBox.offsetHeight); //4利用这个比例计算距离后赋值给右侧的图片
objBigBoxImg.style.left=-percentX*(objBigBoxImg.offsetWidth-objBigBox.offsetWidth)+"px";
objBigBoxImg.style.top=-percentY*(objBigBoxImg.offsetHeight-objBigBox.offsetHeight)+"px";
} }
</script>
</head>
<body>
<div id="demo">
<div id="small-box">
<div id="mark"></div>
<div id="float-box"></div>
<img src="https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg_430x430q90.jpg"/>
</div>
<div id="big-box">
<img src="https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg"/>
</div>
</div>
</body>
</html>

个人感觉MarkBox是多余的操作,于是我将上述代码中与markBox相关的操作去掉,如下:

<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>放大镜</title>
<style>
* {
margin: 0;
padding: 0
}
#demo {
display: block;
width: 323px;
height: 430px;
margin: 5px;
position: relative;
border: 1px solid #ccc;
}
#small-box {
position: relative;
z-index: 1;
}
#float-box {
display: none;
width: 160px;
height: 120px;
position: absolute;
background: #ffffcc;
border: 1px solid #ccc;
filter: alpha(opacity=50);
opacity: 0.5;
}
#big-box {
display: none;
position: absolute;
top: 0;
left: 330px;
width: 323px;
height: 430px;
overflow: hidden;
border: 1px solid #ccc;
z-index: 10;
}
#big-box img {
position: absolute;
z-index: 5
}
</style>
<script>
//页面加载完毕后执行
window.onload = function () {
//找五个个元素:demo,smallBox,foatBox,bigfloatBox,imgs,
var objDemo=document.getElementById("demo");
var objSmallBox=document.getElementById("small-box");
var objFloatBox=document.getElementById("float-box");
var objBigBox=document.getElementById("big-box");
var objBigBoxImg=objBigBox.getElementsByTagName("img")[0]; //给小盒子添加事件,移入和移出
//移入:浮动的box和和bigBox显示
objSmallBox.onmouseover=function(){
objFloatBox.style.display="block";
objBigBox.style.display="block";
}
//移除:浮动的box和bigBox隐藏
objSmallBox.onmouseout=function(){
objFloatBox.style.display="none";
objBigBox.style.display="none";
} //给小盒子添加鼠标移动事件
objSmallBox.onmousemove=function(ev){
var _event=ev||window.event;//做兼容性,兼容IE
//1计算值:
var left=_event.clientX-objDemo.offsetLeft-objSmallBox.offsetLeft-objFloatBox.offsetWidth/2;
var top=_event.clientY-objDemo.offsetTop-objSmallBox.offsetTop-objFloatBox.offsetHeight/2; //5.优化,在前面加判断,不让其溢出,加判断
if(left<0) left=0;
if(top<0) top=0;
if(left>objSmallBox.offsetWidth-objFloatBox.offsetWidth)
left=objSmallBox.offsetWidth-objFloatBox.offsetWidth;
if(top>objSmallBox.offsetHeight-objFloatBox.offsetHeight)
top=objSmallBox.offsetHeight-objFloatBox.offsetHeight; //2把值赋值给放大镜
objFloatBox.style.left=left+"px";
objFloatBox.style.top=top+"px"; //3计算比例
var percentX=left/( objSmallBox.offsetWidth-objFloatBox.offsetWidth);
var percentY=top/( objSmallBox.offsetHeight-objFloatBox.offsetHeight); //4利用这个比例计算距离后赋值给右侧的图片
objBigBoxImg.style.left=-percentX*(objBigBoxImg.offsetWidth-objBigBox.offsetWidth)+"px";
objBigBoxImg.style.top=-percentY*(objBigBoxImg.offsetHeight-objBigBox.offsetHeight)+"px";
} }
</script>
</head>
<body>
<div id="demo">
<div id="small-box">
<div id="float-box"></div>
<img src="https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg_430x430q90.jpg"/>
</div>
<div id="big-box">
<img src="https://img.alicdn.com/imgextra/https://img.alicdn.com/bao/uploaded/i2/1026430696/O1CN011H0o7UD6ZwLT3vl_!!1026430696.jpg"/>
</div>
</div>
</body>
</html>

运行效果相同

原生js实现放大镜的更多相关文章

  1. 原生js实现放大镜效果

    今天做任务的时候,有一个任务就是让实现电商网站常用的放大镜效果,类似于这样的效果,之前并没有做过这种放大镜效果,刚开始的思路是对图片进行裁剪,但是后来发现实在是难以实现,于是求助了万能的谷歌,发现一个 ...

  2. 用JS实线放大镜的效果

    今天花了点时间,复习了下使用原生JS实线放大镜的效果.在制作过程中,也是很到了一些问题,在这里总结下. HTML代码如下: <div id="preview"> < ...

  3. 原生js实现的放大镜效果

    这是我用原生js写的放大镜效果,与各种各样的框架技术相比,我喜欢使用原生的js,在这里,想和大家一起谈谈原生和框架技术的理解与个人喜好. <!DOCTYPE HTML><html&g ...

  4. jq商品展示图放大镜 and 原生js和html5写的放大镜效果 ~~效果不错

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

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

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

  6. 原生JS封装Ajax插件(同域&&jsonp跨域)

    抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...

  7. 常用原生JS方法总结(兼容性写法)

    经常会用到原生JS来写前端...但是原生JS的一些方法在适应各个浏览器的时候写法有的也不怎么一样的... 今天下班有点累... 就来总结一下简单的东西吧…… 备注:一下的方法都是包裹在一个EventU ...

  8. 原生JS实现"旋转木马"效果的图片轮播插件

    一.写在最前面 最近都忙一些杂七杂八的事情,复习软考.研读经典...好像都好久没写过博客了... 我自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的, ...

  9. 再谈React.js实现原生js拖拽效果

    前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...

随机推荐

  1. vim插件的安装方式 -- vim注释插件和doxygen函数注释生成插件-ctrlp插件-tabular等号对齐 插件

    使用unzip的时候 指定 -d选项, 是说明解压到的 目标地址. 这个参数还是比较方便的, 比直接unzip到当前目录, 然后在去拷贝到目标目录, 然后再删除当前目录中的解压文件夹, 方便多了. 使 ...

  2. #2718. 「NOI2018」归程 kruskal重构树

    链接 https://loj.ac/problem/2718 思路 我们希望x所在的连通块尽量的大,而且尽量走高处 离线的话可以询问排序,kruskal过程中更新答案 在线就要用kruskal重构树 ...

  3. p3396 哈希冲突(暴力)

    想了好久,没想到优秀的解法,结果是个暴力大吃一静.jpg 分类讨论,预处理\(p\le \sqrt{n}\) 的情况,其他直接暴力,复杂度\(O(n \sqrt{n} )\) #include < ...

  4. 论文笔记:Semantic Segmentation using Adversarial Networks

    Semantic Segmentation using Adversarial Networks 2018-04-27 09:36:48 Abstract: 对于产生式图像建模来说,对抗训练已经取得了 ...

  5. (转)Introductory guide to Generative Adversarial Networks (GANs) and their promise!

    Introductory guide to Generative Adversarial Networks (GANs) and their promise! Introduction Neural ...

  6. 51nod 1615 跳跃的杰克

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1615 题意: 思路:一开始是觉得一旦超过了终点,中间某个地方往相反地方跳 ...

  7. IntelliJ IDEA java selenium

    // // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler ...

  8. _faction

    一.自定义阵营独立于联盟,部落,联盟和部落玩家可以加入同一阵营 二._function_menu表可以配置自定义阵营开启 二.配合_pvp表,可以实现区域的自定义阵营PVP 三.配合_req表fact ...

  9. 下载安装Android sdk tools

    安装java: https://www.cnblogs.com/sea-stream/p/5815957.html 下载地址:https://www.androiddevtools.cn/ 选择版本 ...

  10. Ubuntu18.04的网络配置

    网卡与DNS配置 1)打开命令窗口(右键单机桌面选择Open Terminal或者用快捷键Ctrl+Alt+T打开终端),输入ip a查看自己的网卡编号 2)输入命令sudo vim /etc/net ...