js hover图片放大不遮挡_CSS3+JS 实现放大镜

注意:

  • 看懂本文需要:
    • 懂中文 :)
    • 学习过 JavaScript 和 css
  • 代码较长,框框可左右滑动哦
  • 您的观看和点赞是对本公众号最大力的支持 ~~

原文链接:

  • https://blog.csdn.net/qq_43624878/article/details/110197749 CSS3+JS完美实现放大镜模式

效果

97c49944b3d0c81d76ec4caa790a4813.gif
test

核心

  • CSS函数,如:calc() —— 动态计算;var() —— 使用自定义变量
  • CSS伪元素:::before/after —— 方便控制,而且独立于文档流之外,易于渲染
  • JS API:offsetX/offsetY:相对父节点区域左上角定位

其实我们具体要实现的就是:在鼠标移入时显示出来一个小圆圈(跟着鼠标走),这个小圆圈到哪,哪里的图片区域就放大相应的倍数并且显示在圆圈内。

为什么要用offset API?其实根据上面的描述,我们需要实时获取鼠标的左偏移量和上偏移量,而这两个偏移量是相对父节点的。通过左偏移量和上偏移量结合calc()即可计算放大镜显示内容相对父节点的显示位置。不难找到在鼠标事件对象中,js为我们提供了如下API:

  • screenX/screenY:相对屏幕区域左上角定位,若发生滚动行为,则相对该区域定位
  • pageX/pageY:相对网页区域左上角定位
  • clientX/clientY:相对浏览器可视区域左上角定位
  • offsetX/offsetY:相对父节点区域左上角定位,若无父节点则相对定位

但相较而言唯一符合要求的就只有offset“相对于父元素”了。

<div class="bruce">
    <div class="magnifier">div>
div>
let magnifier=document.querySelector(".magnifier");
magnifier.addEventListener("mousemove",e=>{
 //控制“镜子”小圆圈的移动
});

放大镜显示内容其实就是将原图像放大N倍,通过上述偏移量按照比例截取一定区域显示内容。

先定义相关的css变量。我们设定放大倍率为2.5倍,那么被放大图像的宽高也是原来宽高的2.5倍。声明两个变量,分为为 --x--y

:root{
    --ratio: 2.5;
    --box-w: 600px;
    --box-h: 400px;
    --outbox-w: calc(var(--box-w) * var(--ratio));
    --outbox-h: calc(var(--box-h) * var(--ratio));
}
.bruce{
    margin-top: 50px;
}
.magnifier{
    --x:0;
    --y:0;
    overflow: hidden;
    position: relative;
    width: var(--box-w);
    height: var(--box-h);
    background: url("img/nan.png") no-repeat center/100% 100%;
    cursor: grabbing;
}

图片以背景图的形式展示,方便控制大小。

很显然在这个场景下无需插入子节点作为放大镜的容器了,使用::before即可!

放大镜在使用时宽高为100px,不使用时宽高为0。通过绝对定位布局放大镜随鼠标移动的位置,即声明left和top,再通过声明 transform:translate(-50%,-50%) 将放大镜补位,使放大镜中心与鼠标光标位置一致。由于声明left和top定位放大镜的位置,还可以声明 will-change 改善left和top因改变而引发的性能问题!而且用CSS解决这些问题的另一个好处就是:借助于伪元素/伪类,我们可以将一些比较细节的东西用CSS解决,而不是寄托于“繁重”的JavaScript。比如:鼠标移入样式hover:

.magnifier::before{
    --size: 0;
    position: absolute;
    left: var(--x);
    top: var(--y);
    border-radius: 100%;
    width: var(--size);
    height: var(--size);
    box-shadow: 1px 1px 3px rgba(0,0,0,.5);
    content: "";
    will-change: left,top;
    transform: translate(-50%,-50%);
}
.magnifier:hover::before{
    --size: 100px;
}

接下来使用background实现(展示)放大镜内容。依据放大倍率为2.5倍,那么可声明size: --outbox-w --outbox-h,通过 position-x 和 position-y 移动背景即可,最终可连写成 background:#333 url(背景图片) no-repeat var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h) 。其中 --scale-x 和 --scale-y 对应 position-x 和 position-y (即background-position),用于随着鼠标移动而改变背景位置。

--scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x));
--scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y));
12

那么上面mousemove函数中改变镜子的“位置坐标”就可以这么写了:

e.target.style.setProperty("--x",`${e.offsetX}px`);
e.target.style.setProperty("--y",`${e.offsetY}px`);
12

so eazy~

最终的CSS内容如下:

:root{
    --ratio: 2.5;
    --box-w: 600px;
    --box-h: 400px;
    --outbox-w: calc(var(--box-w) * var(--ratio));
    --outbox-h: calc(var(--box-h) * var(--ratio));
}
.bruce{
    margin-top: 50px;
}
.magnifier{
    --x:0;
    --y:0;
    overflow: hidden;
    position: relative;
    width: var(--box-w);
    height: var(--box-h);
    background: url("img/nan.png") no-repeat center/100% 100%;
    cursor: grabbing;
}
.magnifier::before{
    --size: 0;
    --scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x));
    --scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y));
    position: absolute;
    left: var(--x);
    top: var(--y);
    border-radius: 100%;
    width: var(--size);
    height: var(--size);
    background: #333 url("img/nan.png") no-repeat var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h);
    box-shadow: 1px 1px 3px rgba(0,0,0,.5);
    content: "";
    will-change: left,top;
    transform: translate(-50%,-50%);
}
.magnifier:hover::before{
    --size: 100px;
}

若是::before中想要用一张本身就是2倍大小的图片,则background中将--outbox-w--outbox-h替换为原本的--box-w--box-h 再做适当的微调即可。

注意看你放大镜中的内容,它表明不只是简单的图片的放大,所以才有了 var(--size) / var(--ratio) 这一段代码;关于css中修改css3自定义变量:我仍然认为只能在“同级同属”范围内才能修改并显示成功。

完整代码

已加上注释,注意修改图片路径

html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Titletitle>
  <style>:root {--ratio: 2.5; /* 放大倍率 */--box-w: 600px; /* 原始宽度 */--box-h: 400px; /* 原始高度 */--outbox-w: calc(var(--box-w) * var(--ratio)); /* 放大后宽度 */--outbox-h: calc(var(--box-h) * var(--ratio)); /* 放大后高度 */
    }/* 调一下框框位置 */.bruce {margin-top: 50px;
    }/* 界面 */.magnifier {--x: 0;--y: 0;overflow: hidden; /* 溢出隐藏边框的内容 */position: relative; /* 相对定位 */width: var(--box-w); /* 应用root定义的宽度 */height: var(--box-h); /* 应用root定义的高度 *//* 注意:如果同时设置了position和size两个属性,应该用左斜杠“/”,而不是用空格把两个参数值隔开:position/size */background: url("1.jpg") no-repeat center/100% 100%; /* 调整图片宽高,设置背景图片居中不重复显示 */cursor: grabbing; /* 定义鼠标形状为手势 */
    }.magnifier::before {--size: 0;/* 原图和放大之后的图片比例做计算 */--scale-x: calc(var(--size) / var(--ratio) - var(--ratio) * var(--x)); /* 显示放大后图片的x轴 */--scale-y: calc(var(--size) / var(--ratio) - var(--ratio) * var(--y)); /* 显示放大后图片的y轴 *//* 绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于: */position: absolute;left: var(--x); /* 左距离 */top: var(--y); /* 顶距离 */border-radius: 100%; /* 设置为圆形 */width: var(--size); /* 设置放大镜宽度 */height: var(--size); /* 设置放大镜高度 */background: #333 url("1.jpg") no-repeat var(--scale-x) var(--scale-y)/var(--outbox-w) var(--outbox-h);/* 设置阴影 */box-shadow: 1px 1px 3px rgba(0, 0, 0, .5);content: ""; /* content属性一般用于:before, :after伪元素中,用于呈现伪元素的内容 */will-change: left, top; /* 性能优化 *//* 设置放大镜 xy向左偏移一半,因为放大镜本身是一个正方形 */transform: translate(-50%, -50%);
    }.magnifier:hover::before {--size: 100px; /* 当选择鼠标指针浮动在其上的元素,调整样式 */
    }style>
head>
<body>
<div class="bruce">
  <div class="magnifier">div>
div>
<script>let magnifier = document.querySelector(".magnifier");// 添加鼠标移动事件的监听
  magnifier.addEventListener("mousemove", e => {//控制“镜子”小圆圈的移动
    e.target.style.setProperty("--x", `${e.offsetX}px`);
    e.target.style.setProperty("--y", `${e.offsetY}px`);
  });script>
body>
html>

end

您的观看和点赞是对本公众号最大力的支持 ~~

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

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

相关文章

python装饰器class_Python中的各种装饰器详解

Python装饰器&#xff0c;分两部分&#xff0c;一是装饰器本身的定义&#xff0c;一是被装饰器对象的定义。 一、函数式装饰器&#xff1a;装饰器本身是一个函数。 1.装饰函数&#xff1a;被装饰对象是一个函数 [1]装饰器无参数&#xff1a; a.被装饰对象无参数&#xff1a; &g…

odoo controller 继承

方式一&#xff1a; 继承基类&#xff0c;直接重写方法 from odoo.addons.web.controllers.main import Exportclass PsExport(Export): http.route(/web/export/get_fields, typejson, auth"user") def get_fields(self, model, prefix, parent_name , import_co…

python字符串startswith_Python 字符串 startswith() 使用方法及示例

Python 字符串 startswith() 使用方法及示例如果字符串以指定的前缀(字符串)开头&#xff0c;则startswith()方法将返回True。如果不是&#xff0c;则返回False。startswith()的语法为&#xff1a;str.startswith(prefix[, start[, end]])startswith()参数startswith()方法最多…

odoo连接外部数据库

odoo框架默认的访问时Postgres数据库&#xff0c;但在实际的应用场景中&#xff0c;不可避免的使用到其他数据库&#xff0c;所以有必要研究如何连接其他第三方数据库&#xff0c;这里分享下OCA的相关模块&#xff0c;具体的源代码在这里。 我将第三方的数据库需要连接的情况汇…

整型和bcd的对应关系_微信与多闪之争背后,好友关系链到底是如何窃取的?

这几天从发布到全面推广&#xff0c;多闪已经快速的超越100万用户&#xff0c;迅速占领了appsotre榜首&#xff0c;在七麦数据中也是蝉联第一。但因多闪包括头条产品登录采取都支持【微信第三方登录】。很多用户都反馈是否自己的关系链被多闪、甚至是抖音窃取&#xff0c;并且腾…

线程同步,线程不同步_同步多线程集成测试

线程同步,线程不同步测试线程非常困难&#xff0c;这使得为被测多线程系统编写良好的集成测试非常困难。 这是因为在JUnit中&#xff0c;测试代码&#xff0c;被测对象和任何线程之间没有内置的同步。 这意味着&#xff0c;当您必须为创建并运行线程的方法编写测试时&#xff0…

ehcache 默认大小_简单的使用ehcache

ehcache是一个用Java实现的使用简单&#xff0c;高速&#xff0c;实现线程安全的缓存管理类库&#xff0c;ehcache提供了用内存&#xff0c;磁盘文件存储&#xff0c;以及分布式存储方式等多种灵活的cache管理方案。同时ehcache作为开放源代码项目&#xff0c;采用限制比较宽松…

JS定时器使用,定时定点,固定时刻,循环执行

本文概述&#xff1a;本文主要介绍通过JS实现定时定点执行&#xff0c;在某一个固定时刻执行某个函数的方法。比如说在下一个整点执行&#xff0c;在每一个整点执行&#xff0c;每隔10分钟定时执行的方法。 JavaScript中有两个定时器方法&#xff1a;setTimeout&#xff08;&am…

axios 跨域_当遇到跨域开发时,我们如何处理好前后端配置和请求库封装

我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器.这个时候我们只需要请求后端服务器的接口即可实现系统的业务功能开发.这个过程中会涉及到web页面…

Java数据类型和标识符

在本教程中&#xff0c;我们将了解Java中的数据类型和标识符。 Java语言具有丰富的数据类型实现。 数据类型指定大小和可以存储在标识符中的值的类型。 Java数据类型分为两类&#xff1a; 原始数据类型 非原始数据类型 原始类型 Java定义了八种原始数据类型&#xff1a;字…

哈罗顺风车送到终点吗_没有了顺风车,滴滴“特惠拼车”来了!比拼车更低价,比顺风车更安全吗?...

近日&#xff0c;有网友表示&#xff0c;滴滴出行App内出现了“特惠拼车”功能&#xff0c;据悉&#xff0c;该功能主要给乘客提供长距离拼车出行的优惠折扣。如果拼车价格为44.8元&#xff0c;那“特惠拼车”的价格为30.7元。但是该功能目前还未在上海出现。近日&#xff0c;有…

管理角色认知-工程师到管理者角色发生了哪些变化?

背景 不同等级的管理者需求不同&#xff1b; 管理者需求说明新经理提供管理相关的工具和方法能力层面&#xff0c;术高级经理提升角色认知认知和理解&#xff0c;道&#xff0c;系统通过认知上的改变达到能力和行为上的改善一个人的行为&#xff0c;能力&#xff0c;价值观都源…

axure 小程序 lib_小程序定制开发的步骤有哪些?

经过两年多的微信小程序开发&#xff0c;各种功能应用变得越来越成熟&#xff0c;越来越多的企业和企业正在开发微信小程序用于在线营销。如果您的公司尚未开发成都小程序&#xff0c;它将变得越来越凶猛。在竞争激烈的市场环境中&#xff0c;将失去许多获得和营销客户的机会。…

java 检查打印机状态_爱普生打印机常见故障有哪些 爱普生打印机故障解决方法【详解】...

任何设备在使用一段时间后都会出现一些小问题&#xff0c;打印机也不例外&#xff0c;那么爱普生打印机常见的故障有哪些 &#xff0c;出现问题该怎么解决呢&#xff1f;下面小编就来分享2018爱普生打印机故障解决方法 &#xff0c;一起来看看吧&#xff01;一、故障现象 &a…

eureka 之前的服务如何关闭_干货分享 | 服务注册中心Spring Cloud Eureka部分源码分析...

友情提示&#xff1a;全文13000多文字&#xff0c;预计阅读时间10-15分钟Spring Cloud Eureka作为常用的服务注册中心&#xff0c;我们有必要去了解其内在实现机制&#xff0c;这样出现问题的时候我们可以快速去定位问题。当我们搭建好Eureka Server服务注册中心并启动后&#…

局部变量写在循环内还是外_循环内的局部变量和性能

局部变量写在循环内还是外总览 有时会出现一个问题&#xff0c;即分配一个新的局部变量需要多少工作。 我的感觉一直是&#xff0c;代码已优化到成本为静态的程度&#xff0c;即一次执行&#xff0c;而不是每次运行都执行一次。 最近&#xff0c; Ishwor Gurung建议考虑将一些…

csp-s模拟测试44「D·E·F」

用心出题,用脚造数据 乱搞场 1 #include<bits/stdc.h>2 #define re register3 #define int long long4 #define inf 0x7ffffffffffffff5 using namespace std;6 int n,a[100010],b[100010],ansinf;7 double st,ed;8 inline int read(){9 re int a0,b1; re char chget…

c++中的new_怎么在java中创建一个自定义的collector

简介在之前的java collectors文章里面&#xff0c;我们讲到了stream的collect方法可以调用Collectors里面的toList()或者toMap()方法&#xff0c;将结果转换为特定的集合类。今天我们介绍一下怎么自定义一个Collector。Collector介绍我们先看一下Collector的定义&#xff1a;Co…

Java 9中的新Regex功能

最近&#xff0c;我收到了Packt出版的Anubhava Srivastava提供的免费书籍“ Java 9 Regular Expressions” 。 这本书是一个很好的教程&#xff0c;它向任何想学习正则表达式并从头开始的人介绍。 那些知道如何使用正则表达式的人可能仍然很有趣&#xff0c;以重申其知识并加深…

c语言实现二分法_C语言实现二分法求解方程在区间内的根

C语言实现二分法求解方程在区间内的根。设有非线性方程&#xff1a;其中&#xff0c; 为 上连续函数且设 (不妨设方程在 内仅有一个实根)&#xff0c;求上述方程实根的二分法过程&#xff0c;就是将含根区间[a,b]逐步分半&#xff0c;检查函数值符号的变化&#xff0c;以便确定…