仿京东PC网页商品详情的放大镜效果(原理+代码)

news2024/11/17 0:01:42

实现效果

黑色只不过是转gif出问题而已

  

准备工作

1. 访问该网址,理解我们要弄的放大镜效果,鼠标经过商品图片,显示一个黄色的放大选区,右边显示该选区的大图。

2. 获取商品图片和商品大图

【摩托罗拉moto X30 Pro】摩托罗拉moto X30 Pro 全新骁龙8+ 2亿像素 125W闪充+50W无线充 144Hz曲面臻彩屏 5G手机 12GB+256GB 墨韵黑【行情 报价 价格 评测】-京东

商品图片:

https://img12.360buyimg.com/n1/s450x450_jfs/t1/36890/26/19707/96919/63b05265F4b433f6c/6c7017a0c9caa09a.jpg

 商品大图:

https://img12.360buyimg.com//n0/jfs/t1/36890/26/19707/96919/63b05265F4b433f6c/6c7017a0c9caa09a.jpg

代码实现

ps: 标红的地方需要懂

1、项目结构:

​ 

2、简单的网页布局

只需要准备左边一个正方形盒子右边一个大正方形盒子即可

3、商品大图在右边大盒子局部显示

商品大图不要设置宽高属性,保留其大图800*800的尺寸,商品大图在右边大盒子局部显示大图比右盒子大,父盒子 overflow:hidden

效果: 

<body>
    <div class="left-box">
        <img src="./images/small.jpg" alt="">
        <div class="right-box">
            <img src="./images/big.jpg" alt="">
        </div> 
    </div>
</body>
* {
    margin: 0;
    padding: 0;
    /* 盒子模型:padding和边框都不会撑大盒子 */
    box-sizing: border-box;
}

.left-box {
    position: relative;
    margin-top: 100px;
    margin-left: 100px;
    width: 400px;
    height: 400px;
    border: 1px solid #ccc;
}

.left-box>img{
    width: 100%;
}

.right-box {
    position: absolute;
    top: 0;
    left: 400px;
    width: 540px;
    height: 540px;
    border: 1px solid #ccc;
    /* big-box 下的img不设置宽高,就是显示大图本身大小 800*800 */
    /* 父盒子局部显示大图 */
    overflow: hidden;
}

4、放大镜选区效果布局

选区在左边盒子里,所以是左边盒子儿子,透明度 opacity: 0.5; 鼠标的样式要变成移动的 cursor: move;

5、放大镜选区 和 右侧大盒子 隐藏

隐藏 display: none;(不保留空间)

6、鼠标经过左边的盒子,显示放大镜选区 和 右侧大盒子。

使用js注册监听鼠标经过mouseover和鼠标离开mouseout事件 addEventListener('mouseover', function() {})

7、选区的移动位置1

放大镜选区跟随鼠标移动,鼠标的移动范围是在左边盒子里,不是在放大镜选区里,所以应该是左边的盒子注册监听鼠标移动事件 addEventListener('mousemove', function() {})


放大镜选区跟随鼠标移动,已知:

  • mousemoveevent对象存在属性pageXpageY,表示当前鼠标在整个网页页面中的位置。
  • 标签元素存在属性offsetLeftoffsetTop,表示当前元素的位置(相对于有定位的父级,如果不存在有定位的父级,则是body)。
  • 标签元素存在属性offsetWidthoffsetHeight,表示当前元素的大小,宽度和高度。
  • 标签元素存在属性style,若想改变有定位标签元素的位置,则修改元素的style.leftstyle.top
  • 标签元素的位置,以左基点计算。

计算,求 左盒子里的鼠标相对于左盒子的位置(style.leftstyle.top

放大镜选区的盒子 在 左盒子中 的位置  (鼠标在选区盒子左基点)=  当前鼠标在整个网页页面中的位置 - 左盒子的位置

8、选区的移动位置2

放大镜选区跟随鼠标移动优化1: 把鼠标放在放大镜选区的中间(鼠标在页面中的位置不变,把选区盒子往左移动一半,往上移动一半


计算: 选区的移动距离 = 放大镜选区的盒子 在 左盒子中 的位置(鼠标在选区盒子中间) =  放大镜选区的盒子 在 左盒子中 的位置  (鼠标在选区盒子左基点) -(放大镜选区的大小 / 2)


 

9、选区的移动范围

放大镜选区跟随鼠标移动优化2,限制选区盒子的移动范围:第8步的移动,会出现选区盒子超出左盒子的现象,所以我们要限制选区盒子的移动范围,这时候鼠标就不需要在放大镜选区中间了。小于最小范围,则使它等于最小范围,超过最大范围,则使它等于最大范围。

超过的图:

限制以后:


范围计算:

最小:选区盒子距离左盒子左边框为0

最大:选区盒子距离左盒子右边框为0,即 左盒子的宽度-选区盒子的宽度


  

选区的移动:

10、右盒子的大小优化。

放大镜选区以后,右盒子显示大图中的相应区域,再这里要构成一种比例关系(因为是正方形,所以就不写高度宽度,直接写大小):


比例1(显示的比例):选区的大小/左盒子的大小 = 右盒子的大小/大图的大小


所以,css中的已知选区盒子大小 250 、左盒子大小400 、大图大小800,则右盒子的大小为250*800/400 = 500,我们之前布局写了540,所以要改成500;

11、大图的移动

放大镜选区以后,右盒子显示大图中的相应区域,所以应该是大图本身相对着父盒子在移动,为了与放大镜选区一致,所以这里也存在一种比例关系:


比例2(移动距离的比例):选区的移动距离/选区的最大移动距离 =  大图的移动距离 / 大图的最大移动距离

大图的移动距离 = 选区的移动距离 * 大图的最大移动距离 / 选区的最大移动距离

大图的最大移动距离:大图距离右盒子右边框为0,即 大图的宽度-右盒子的宽度


注意别忘了,给右盒子大图做定位,大图才能相对右盒子进行移动。

因为是大图相对着右盒子移动,所以要用负号,大图的区域才会在父盒子中显示。

总结

重点是要知道第7步中的已知,以及计算鼠标在盒子中的位置(相对位置),以及理解两个比例关系,这两个比例关系就是等比放大效果的原因,最后就是css也挺重要的,理解相对定位,配合css,js才能作出特效。

完整代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>仿京东PC网页商品详情的放大镜效果</title>
    <link rel="stylesheet" href="./css/index.css">
    <script src="./js/magnifier.js"></script>
</head>
<body>
    <div class="left-box">
        <img src="./images/small.jpg" alt="">
        <div class="magnifier-box"></div>
        <div class="right-box">
            <img src="./images/big.jpg" alt="" class="bigImg">
        </div> 
    </div>  
</body>
</html>
* {
    margin: 0;
    padding: 0;
    /* 盒子模型:padding和边框都不会撑大盒子 */
    box-sizing: border-box;
}

.left-box {
    position: relative;
    margin-top: 100px;
    margin-left: 100px;
    width: 400px;
    height: 400px;
    border: 1px solid #ccc;
}

.left-box>img{
    width: 100%;
}

.right-box {
    position: absolute;
    top: 0;
    left: 400px;
    width: 500px;
    height: 500px;
    border: 1px solid #ccc;
    /* right-box 下的img不设置宽高,就是显示大图本身大小 800*800 */
    /* 父盒子局部显示大图 */
    overflow: hidden;
    display: none;
}

.right-box>img {
    position: absolute;
}

.magnifier-box {
    position: absolute;
    top: 0;
    left: 0;
    width: 250px;
    height: 250px;
    background: rgb(240, 221, 48);
    border: 1px dashed rgb(240, 221, 48);
    /* 整个盒子的透明度 */
    opacity: 0.5;
    /* 鼠标样式变成移动的 */
    cursor: move;
    display: none;
}
// 因为script在DOM之前引入,所以代码要写在onload事件里
// onload:等页面完全加载以后再执行
window.addEventListener('load',function(){
    // 左盒子
    var left = document.querySelector('.left-box');
    // 右盒子
    var right = document.querySelector('.right-box');
    // 放大镜选区
    var magnifier = document.querySelector('.magnifier-box');
    // 鼠标经过 显示
    left.addEventListener('mouseover',function(){
        magnifier.style.display = 'block';
        right.style.display = 'block';
    })
    // 鼠标离开 隐藏
    left.addEventListener('mouseout',function(){
        magnifier.style.display = 'none';
        right.style.display = 'none';
    })
    // 鼠标移动
    left.addEventListener('mousemove',function(event){
        // console.dir(left);
        // 放大镜选区的移动位置(鼠标在选区左基点)
        let magnifierX = event.pageX - left.offsetLeft;
        let magnifierY = event.pageY - left.offsetTop;
        // 放大镜选区的移动位置(鼠标在选区中间)
        let magnifierCenterX = magnifierX - (magnifier.offsetWidth / 2);
        let magnifierCenterY = magnifierY - (magnifier.offsetHeight / 2);
        // 放大镜选区的最大移动距离,因为是正方形,所以计算一个就行
        let magnifierMaxRangeX = left.offsetWidth - magnifier.offsetWidth
        // let maxRangeY = left.offsetHeight - magnifier.offsetHeight
        // 限制选区移动范围,宽高都要设置
        if(magnifierCenterX < 0) {
            magnifierCenterX = 0
        }
        if(magnifierCenterX > magnifierMaxRangeX) {
            magnifierCenterX = magnifierMaxRangeX
        }
        if(magnifierCenterY < 0) {
            magnifierCenterY = 0
        }
        if(magnifierCenterY > magnifierMaxRangeX) {
            magnifierCenterY = magnifierMaxRangeX
        }
        // 放大镜选区的移动
        magnifier.style.left = magnifierCenterX  + 'px';
        magnifier.style.top = magnifierCenterY + 'px';
        // 大图
        let bigImg = document.querySelector('.bigImg');
        // 大图的最大移动距离
        let bigImgXMaxRange = bigImg.offsetWidth - right.offsetWidth
        // 大图的移动位置
        let bigImgX = magnifierCenterX * bigImgXMaxRange / magnifierMaxRangeX 
        let bigImgY = magnifierCenterY * bigImgXMaxRange / magnifierMaxRangeX
         // 大图的移动
        bigImg.style.left = -bigImgX  + 'px';
        bigImg.style.top = -bigImgY + 'px';
    })
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/186515.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

protocol-buffers 基础(一)

protocol-buffers 官网 Github 一、概述 协议缓冲区&#xff08;protocol-buffers&#xff09;是一种与语言无关、与平台无关的可扩展机制&#xff0c;用于序列化结构化数据。 协议缓冲区提供了一种与语言无关、与平台无关、可扩展的机制&#xff0c;用于以向前兼容和向后兼…

【深度学习笔记】全卷积网络FCN及 ROI Pooling 和 ROI Align 的区别

问题 FCN 是语义分割的开山之作,没理由不了解。最近发现学习最快的方式还是看别人的教学视频,很多时候博客看一大推,没几个能讲地明白的,确实啊,视频都得用四五十分钟的东西,一个博客得写得多详细才能覆盖到方方面面呀,以后还是先借助视频来学习,然后再根据源码进一步…

leetcode 1669. 合并两个链表【python3一次遍历方法详细过程描述】

题目 给你两个链表list1和list2&#xff0c;它们包含的元素分别为n个和m个。请你将list1中下标从a到b的全部节点都删除&#xff0c;并将list2接在被删除节点的位置。 下图中蓝色边和节点展示了操作后的结果&#xff1a; 请你返回结果链表的头指针。 示例1&#xff1a; 输入&…

网络原理(TCP/IP五层协议)(二)

目录TCP 中的一些主要机制1.确认应答机制(安全机制)2.超时重传机制(安全机制)3.连接管理机制(安全机制)如何建立连接&#xff1a;三次握手如何断开连接&#xff1a;四次挥手TCP 中的一些主要机制 TCP对数据传输提供的管控机制&#xff0c;主要体现在两个方面&#xff1a;安全和…

C++右值引用相关

能够取地址值、有名字的就是左值&#xff0c;不能取地址值、没名字的就是右值。 移动语义 将内存的所有权从一个对象转换到另一个对象&#xff0c;高效的移动来替换效率低下的赋值。 完美转发 定义一个函数模板&#xff0c;该函数模板可以接受任意类型参数&#xff0c;然后将参…

即时通讯开发之TCP/IP中的IP协议、ARP协议

IP 协议是 TCP/IP 协议的核心,所有的 TCP,UDP,IMCP,IGCP 的数据都以 IP 数据格式传输。要注意的是,IP 不是可靠的协议,这是 说,IP 协议没有提供一种数据未传达以后的处理机制--这被认为是上层协议--TCP 或 UDP 要做的事情。所以这也就出现了 TCP 是一个可靠的协议,而 UDP 就没有…

前端开发:JS中关于八皇后算法的使用

前言 在前端开发过程中&#xff0c;关于算法的使用也是非常常见的操作&#xff0c;尤其是处理一些复杂的业务场景&#xff0c;还有就是前端获取到后端返回的复杂结构的数据&#xff0c;所以说前端开发中处处都有算法使用的场景。开发者从接触编程开发开始&#xff0c;就与算法脱…

Java switch case语句详解

if…else 语句可以用来描述一个“二岔路口”&#xff0c;我们只能选择其中一条路来继续走&#xff0c;然而生活中经常会碰到“多岔路口”的情况。switch 语句提供了 if 语句的一个变通形式&#xff0c;可以从多个语句块中选择其中的一个执行。switch 语句格式switch 语句是 Jav…

44物体检测算法:R-CNN,SSD,YOLO【动手学深度学习v2】

44物体检测算法&#xff1a;R-CNN&#xff0c;SSD&#xff0c;YOLO【动手学深度学习v2】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV1if4y147hS/?spm_id_from333.337.search-card.all.click&vd_source75dce036dc8244310435eaf03de4e330 目标…

使用Springboot 2.7+Websocket+js实现服务端消息实时推送

文章目录诉求相关技术相关步骤项目创建编写相关配置消息逻辑处理使用JavaScript实现Websocket的前端功能功能测试诉求 模拟服务端主动推送消息给客户端&#xff0c;同时展示客户端发送给客户端的消息以及服务端推送给客户的消息。 相关技术 Springboot(2.7.0)Websocketjavascr…

Elasticsearch7.8.0版本入门——JavaAPI操作(文档操作)

目录一、pom文件依赖二、创建实体对象类三、文档操作代码示例3.1、创建文档代码示例3.2、修改文档代码示例3.3、查询文档代码示例3.4、删除文档代码示例一、pom文件依赖 引入相关依赖 <!-- elasticsearch 依赖 --> <dependency><groupId>org.elasticsearch&l…

【Pytorch】自定义autograd函数,使用graphviz画出计算图

使用pytorch.autograd.Function构建一个自动求导层1. 手工设计一个线性运算层2. 使用pytorch.autograd.Function编码实现3. graphviz进行可视化1. 手工设计一个线性运算层 设输入为x\bold{x}x&#xff0c;参数为w\bold{w}w和b\bold{b}b&#xff0c;运算如下&#xff1a; yw⊙x…

Tips for Confluence Administrators: Part 3

上一篇Part 2中&#xff0c;我们谈到了Confluence的一些已知Bug&#xff0c;例如&#xff1a;从垃圾桶中恢复同名页面不应覆盖现有页面复制/粘贴表格单元格无法按预期工作无法复制表头嵌套表格无法调整大小请不要吝惜你的投票&#xff0c;这有助于提高Atlassian修复它们的优先级…

四、Maven详细教程

本教程相关资料&#xff1a;https://www.aliyundrive.com/s/wMiqbd4Zws6 Maven是专门用于管理和构建Java项目的工具&#xff0c;它的主要功能有&#xff1a; 提供了一套标准化的项目结构 提供了一套标准化的构建流程&#xff08;编译&#xff0c;测试&#xff0c;打包&#xf…

MacOs安装Redis并设置为开机、后台启动

前言 最近闲来无事&#xff0c;将自己的MBP系统重装里&#xff0c;导致里面原来安装的软件都需要重新安装&#xff0c;今天记录一下MacOs安装Redis并设置为开机启动、后台启动的步骤&#xff0c;安装过程略有波折&#xff0c;参考里几篇文章才搞定。 一、安装Redis 两种方式…

【JavaEE】线程池

目录 线程池概念 线程池优点 使用线程池 Executor接口&#xff1a; ThreadPoolExecutor类&#xff1a; 构造方法 Executors工厂类&#xff1a; 工厂方法 线程池中的常用方法 线程池的工作流程 线程池的状态 RUNNING SHUTDOWN STOP TIDYING TERMINATED 简单实现…

Android10 开机向导流程

最近在弄开机向导&#xff0c;网上查了查&#xff0c;基本都是参照系统的​​​​​​Provision应用来做的&#xff0c;而且还要将apk打包到系统目录下的pri-app目录下&#xff0c;打包到其他目录下不行&#xff0c;参照着做是没问题&#xff0c;但是好奇为什么要这么做&#x…

esp32连接阿里云物联网平台进行MQTT通信

前提&#xff1a;IDE是采用arduino IDE&#xff0c;arduino使用的库是pubsubclient 开发板可以使用esp32&#xff08;esp8266也是一样的&#xff09; 已经学会pubsubclient库的基本使用 使用pubsubclient 库连接阿里云物联网平台 const char* ssid "........"; c…

java ssm校园勤工俭学助学志愿者兼职系统 idea maven

本论文主要论述了如何使用JSP技术开发一个校园勤工俭学兼职系统&#xff0c;本系统将严格按照软件开发流程进行各个阶段的工作&#xff0c;采用B/S架构&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述校园勤工俭学兼职系统的当前背景以及系统开发的…

使用CCProxy+Proxifier实现代理

目录1.使用场景2.什么是网络代理&#xff1f;3.CCProxy3.1 说明3.2 下载安装3.3 使用说明4.Proxifier4.1 说明4.2 下载安装4.3 使用说明4.4 Proxifier CPU占用率高问题解决1.使用场景 很多时候当我们访问某个网络&#xff08;例如&#xff1a;校园网、企业网&#xff09;&#…