原生js实现放大镜
效果:
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实现放大镜的更多相关文章
- 原生js实现放大镜效果
今天做任务的时候,有一个任务就是让实现电商网站常用的放大镜效果,类似于这样的效果,之前并没有做过这种放大镜效果,刚开始的思路是对图片进行裁剪,但是后来发现实在是难以实现,于是求助了万能的谷歌,发现一个 ...
- 用JS实线放大镜的效果
今天花了点时间,复习了下使用原生JS实线放大镜的效果.在制作过程中,也是很到了一些问题,在这里总结下. HTML代码如下: <div id="preview"> < ...
- 原生js实现的放大镜效果
这是我用原生js写的放大镜效果,与各种各样的框架技术相比,我喜欢使用原生的js,在这里,想和大家一起谈谈原生和框架技术的理解与个人喜好. <!DOCTYPE HTML><html&g ...
- jq商品展示图放大镜 and 原生js和html5写的放大镜效果 ~~效果不错
<!DOCTYPE HTML><html lang="en-US"><head> <meta charset="UTF-8&qu ...
- 原生js实现简单的放大镜效果
前言:相信很多同学在浏览购物网站的时候都会用到过放大镜的功能,这个功能在日常的网站也会经常用到.接下来我们开始实现一下它吧: (1)首先了解一下放大镜效果的html架构:如下图,它由两部分组成. ht ...
- 原生JS封装Ajax插件(同域&&jsonp跨域)
抛出一个问题,其实所谓的熟悉原生JS,怎样的程度才是熟悉呢? 最近都在做原生JS熟悉的练习... 用原生Js封装了一个Ajax插件,引入一般的项目,传传数据,感觉还是可行的...简单说说思路,如有不正 ...
- 常用原生JS方法总结(兼容性写法)
经常会用到原生JS来写前端...但是原生JS的一些方法在适应各个浏览器的时候写法有的也不怎么一样的... 今天下班有点累... 就来总结一下简单的东西吧…… 备注:一下的方法都是包裹在一个EventU ...
- 原生JS实现"旋转木马"效果的图片轮播插件
一.写在最前面 最近都忙一些杂七杂八的事情,复习软考.研读经典...好像都好久没写过博客了... 我自己写过三个图片轮播,一个是简单的原生JS实现的,没有什么动画效果的,一个是结合JQuery实现的, ...
- 再谈React.js实现原生js拖拽效果
前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...
随机推荐
- vim插件的安装方式 -- vim注释插件和doxygen函数注释生成插件-ctrlp插件-tabular等号对齐 插件
使用unzip的时候 指定 -d选项, 是说明解压到的 目标地址. 这个参数还是比较方便的, 比直接unzip到当前目录, 然后在去拷贝到目标目录, 然后再删除当前目录中的解压文件夹, 方便多了. 使 ...
- #2718. 「NOI2018」归程 kruskal重构树
链接 https://loj.ac/problem/2718 思路 我们希望x所在的连通块尽量的大,而且尽量走高处 离线的话可以询问排序,kruskal过程中更新答案 在线就要用kruskal重构树 ...
- p3396 哈希冲突(暴力)
想了好久,没想到优秀的解法,结果是个暴力大吃一静.jpg 分类讨论,预处理\(p\le \sqrt{n}\) 的情况,其他直接暴力,复杂度\(O(n \sqrt{n} )\) #include < ...
- 论文笔记:Semantic Segmentation using Adversarial Networks
Semantic Segmentation using Adversarial Networks 2018-04-27 09:36:48 Abstract: 对于产生式图像建模来说,对抗训练已经取得了 ...
- (转)Introductory guide to Generative Adversarial Networks (GANs) and their promise!
Introductory guide to Generative Adversarial Networks (GANs) and their promise! Introduction Neural ...
- 51nod 1615 跳跃的杰克
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1615 题意: 思路:一开始是觉得一旦超过了终点,中间某个地方往相反地方跳 ...
- IntelliJ IDEA java selenium
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler ...
- _faction
一.自定义阵营独立于联盟,部落,联盟和部落玩家可以加入同一阵营 二._function_menu表可以配置自定义阵营开启 二.配合_pvp表,可以实现区域的自定义阵营PVP 三.配合_req表fact ...
- 下载安装Android sdk tools
安装java: https://www.cnblogs.com/sea-stream/p/5815957.html 下载地址:https://www.androiddevtools.cn/ 选择版本 ...
- Ubuntu18.04的网络配置
网卡与DNS配置 1)打开命令窗口(右键单机桌面选择Open Terminal或者用快捷键Ctrl+Alt+T打开终端),输入ip a查看自己的网卡编号 2)输入命令sudo vim /etc/net ...