CSS+JS实现一个鼠标移动的高亮边框效果

embedded/2024/10/19 4:20:42/

一、过程分析

先上效果:

在这里插入图片描述

在Windows系统里有一个很棒的细节效果,元素的渐变高亮边框是可以感知鼠标的,边框的高亮部分会跟随鼠标的移动而移动。

这种效果也是比较常见的,但是实现起来还是需要一点时间和思路的。

首先,我们先完成基础的布局。代码如下:

javascript"><div class="container"><div class="card"><div class="inner"><p>黄鹤楼送孟浩然之广陵</p><p>唐 · 李白</p><p>故人西辞黄鹤楼,烟花三月下扬州。</p><p>孤帆远影碧空尽,唯见长江天际流。</p></div></div><div class="card"><div class="inner"><p>送元二使安西</p><p>唐 · 王维</p><p>渭城朝雨浥轻尘,客舍青青柳色新。</p><p>劝君更尽一杯酒,西出阳关无故人。</p></div></div><div class="card"><div class="inner"><p>春日</p><p>宋 · 朱熹</p><p>胜日寻芳泗水滨,无边光景一时新。</p><p>等闲识得东风面,万紫千红总是春。</p></div></div><div class="card"><div class="inner"><p>小池</p><p>唐 · 杨万里</p><p>泉眼无声惜细流,树阴照水爱晴柔。</p><p>小荷才露尖尖角,早有蜻蜓立上头。</p></div></div><div class="card"><div class="inner"><p>村居</p><p>清 · 高鼎</p><p>草长莺飞二月天,拂堤杨柳醉春烟。</p><p>儿童散学归来早,忙趁东风放纸鸢。</p></div></div><div class="card"><div class="inner"><p>晓出净慈寺送林子方</p><p>唐 · 杨万里</p><p>毕竟西湖六月中,风光不与四时同。</p><p>接天莲叶无穷碧,映日荷花别样红。</p></div></div>
</div>
javascript">body {background-color: black;
}
p {margin: 0;line-height: 2;
}
.container {display: grid;width: 100%;margin-top: 2rem;color: #f0f0f0;grid-template-columns: repeat(3, 1fr);gap: 20px;text-align: center;
}
.card {aspect-ratio: 4/2;border-radius: 8px;background-color: rgba(255, 255, 255, 0.2);
}
.inner {background: #222;display: flex;flex-direction: column;align-items: center;justify-content: center;
}

接下来给 .card 加上相对定位position: relative属性,给 .inner 加上绝对定位position: absolute属性,让card盒子和inner盒子完全重叠在一起。

javascript">.card {aspect-ratio: 4/2;border-radius: 8px;background-color: rgba(255, 255, 255, 0.2);position: relative;
}
.inner {position: absolute;inset: 10px;background: #222;display: flex;flex-direction: column;align-items: center;justify-content: center;
}

为了方便观察,给 .inner 设置 inset: 10px 属性,此属性相当于 left: 10px;top: 10px;right: 10px; bottom: 10px;。

效果如下:

在这里插入图片描述

想要实现高亮的效果,我们还需要在 .card 和 .inner 之间再插入一层,这一层是我们实现高亮的关键!这三层盒子一样大小。

在这里插入图片描述

javascript">.card::before {content: "";position: absolute;inset: 0;background: radial-gradient(closest-side circle, #fff, transparent);
}
.inner {position: absolute;inset: 10px;/* background: #222; */display: flex;flex-direction: column;align-items: center;justify-content: center;
}

为了便于观察,先把.inner的背景色去掉。效果如下:

在这里插入图片描述

看到这里有的人可能已经知道这个中间层用来干什么的了。没错,这不就是一个渐变高亮的效果嘛!我们再在 .card::before 加上一个 transform属性,同时在 .card 上加上 overflow: hidden属性,观察浏览器,神奇的效果出现了!我悟了!

javascript">.card {aspect-ratio: 4/2;border-radius: 8px;background-color: rgba(255, 255, 255, 0.2);position: relative;overflow: hidden;
}
.card::before {content: "";position: absolute;inset: 0;background: radial-gradient(closest-side circle, #fff, transparent);transform: translate(70px, 80px);
}
.inner {position: absolute;inset: 10px;background: #222;display: flex;flex-direction: column;align-items: center;justify-content: center;
}

效果如下:

在这里插入图片描述

原来如此,一个渐变高亮的边框效果不就实现了嘛!

在这里插入图片描述

接下来就是用js代码实现 .card::before 中间层跟随鼠标移动即可。

假如图中的小圆圈为鼠标位置,当鼠标移动到此位置时,只需要计算把每张卡片中间层的中心偏移到鼠标的位置即可。那怎么去计算呢?

首先,获取到每张卡片的元素,监听鼠标移动onmousemove事件,鼠标移动时循环遍历每个卡片元素给每个卡片设置transform: translate(x, y)即可。

x(偏移的水平距离) = 鼠标离视口的水平距离 - 元素离视口的水平距离 - 元素宽度的一半。

y(偏移的垂直距离) = 鼠标离视口的垂直距离 - 元素离视口的垂直距离 - 元素高度的一半。

在这里插入图片描述

代码如下:

javascript">const container = document.querySelector('.container');
const cards = document.querySelectorAll('.card');container.onmousemove = e => {for(const card of cards) {const rect = card.getBoundingClientRect();const x = e.clientX - rect.left - rect.width / 2;const y = e.clientY - rect.top - rect.height / 2;card.style.setProperty('--x', `${x}px`);card.style.setProperty('--y', `${y}px`);}
}

二、完整代码

javascript"><!DOCTYPE html>
<html><head><meta charset="utf-8"><title>b.html</title><style type="text/css">body {background-color: black;}p {margin: 0;line-height: 2;}.container {display: grid;width: 90%;margin: 2rem auto 0;color: #f0f0f0;grid-template-columns: repeat(3, 1fr);gap: 20px;text-align: center;}.card {aspect-ratio: 4/2;border-radius: 8px;background-color: rgba(255, 255, 255, 0.2);position: relative;overflow: hidden;}.card::before {content: "";position: absolute;inset: 0;background: radial-gradient(closest-side circle, #fff, transparent);/* 偏移到看不到的地方 */transform: translate(var(--x, -10000px), var(--y, -10000px));}.inner {position: absolute;inset: 10px;background: #222;display: flex;flex-direction: column;align-items: center;justify-content: center;}</style></head><body><div class="container"><div class="card"><div class="inner"><p>黄鹤楼送孟浩然之广陵</p><p>唐 · 李白</p><p>故人西辞黄鹤楼,烟花三月下扬州。</p><p>孤帆远影碧空尽,唯见长江天际流。</p></div></div><div class="card"><div class="inner"><p>送元二使安西</p><p>唐 · 王维</p><p>渭城朝雨浥轻尘,客舍青青柳色新。</p><p>劝君更尽一杯酒,西出阳关无故人。</p></div></div><div class="card"><div class="inner"><p>春日</p><p>宋 · 朱熹</p><p>胜日寻芳泗水滨,无边光景一时新。</p><p>等闲识得东风面,万紫千红总是春。</p></div></div><div class="card"><div class="inner"><p>小池</p><p>唐 · 杨万里</p><p>泉眼无声惜细流,树阴照水爱晴柔。</p><p>小荷才露尖尖角,早有蜻蜓立上头。</p></div></div><div class="card"><div class="inner"><p>村居</p><p>清 · 高鼎</p><p>草长莺飞二月天,拂堤杨柳醉春烟。</p><p>儿童散学归来早,忙趁东风放纸鸢。</p></div></div><div class="card"><div class="inner"><p>晓出净慈寺送林子方</p><p>唐 · 杨万里</p><p>毕竟西湖六月中,风光不与四时同。</p><p>接天莲叶无穷碧,映日荷花别样红。</p></div></div></div></body><script type="text/javascript">const container = document.querySelector('.container');const cards = document.querySelectorAll('.card');container.onmousemove = e => {for(const card of cards) {const rect = card.getBoundingClientRect();const x = e.clientX - rect.left - rect.width / 2;const y = e.clientY - rect.top - rect.height / 2;card.style.setProperty('--x', `${x}px`);card.style.setProperty('--y', `${y}px`);}}</script>
</html>

http://www.ppmy.cn/embedded/100087.html

相关文章

C/C++控制台贪吃蛇游戏的实现

&#x1f680;欢迎互三&#x1f449;&#xff1a;程序猿方梓燚 &#x1f48e;&#x1f48e; &#x1f680;关注博主&#xff0c;后期持续更新系列文章 &#x1f680;如果有错误感谢请大家批评指出&#xff0c;及时修改 &#x1f680;感谢大家点赞&#x1f44d;收藏⭐评论✍ 一、…

.NET_web前端框架_layui_栅格布局

基础概念 layui:用于简化前端编写的框架。响应式布局&#xff08;Responsive Layout&#xff09;:一种网页设计方法&#xff0c;使网页能够根据不同设备的屏幕尺寸和分辨率自动调整其内容和布局。栅格布局&#xff08;Grid Layout&#xff09;:一种网页设计布局方法&#xff0c…

页面设计任务 商品详情页

目录 成品: 任务描述 源码&#xff1a; 详细讲解&#xff1a; 1.导航栏讲解 2.主体部分 3.图像部分 4.评分部分 5.按钮部分 6.配置信息部分 7.响应式设计 成品: 任务描述 创建一个产品展示页面&#xff0c;包括以下内容&#xff1a; 网页结构&#xff1a;使用 HTM…

一拖二快充线市场需求 - LDR6020

一拖二快充线市场需求与LDR6020应用快充线市场推广 随着科技的飞速发展&#xff0c;智能设备已成为我们日常生活中不可或缺的一部分。从智能手机到平板电脑&#xff0c;再到笔记本电脑&#xff0c;这些设备极大地丰富了我们的生活方式&#xff0c;但同时也带来了一个普遍的问题…

Node.js 文件系统

Node.js 文件系统 Node.js 的文件系统&#xff08;File System&#xff09;模块提供了一种方式&#xff0c;允许开发者使用 JavaScript 代码来访问和操作计算机的文件系统。这个模块是 Node.js 标准库的一部分&#xff0c;因此不需要安装额外的依赖就可以直接使用。文件系统模…

十三、OpenCVSharp的目标检测

文章目录 简介一、传统目标检测方法1. 基于滑动窗口的检测2. 特征提取与分类器结合(如 HOG + SVM)3. 级联分类器二、基于深度学习的目标检测1. YOLO 系列算法2. SSD 算法3. Faster R-CNN 算法三、深度学习目标检测模型的训练和部署四、目标检测的性能评估指标1. 准确率、召回…

开源原型设计工具Penpot

Penpot是一个现代化、开源的协同设计平台&#xff0c;专为跨职能团队打造&#xff0c;提供了强大的在线设计和原型制作功能。 以下是对Penpot的详细介绍&#xff1a; 一、平台特点 开源与免费&#xff1a;Penpot是一个完全免费且开放源代码的项目&#xff0c;允许社区贡献和定…

云计算实训33——高并发负载均衡项目(eleme)

一、配置一主两从mysql服务器&#xff08;mysql5.7&#xff09; 1.主服务器master 下载mysql5.7的包 [rootMysql ~]# rz -E rz waiting to receive. [rootMysql ~]# ls anaconda-ks.cfg mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz #解压 [rootMysql ~]# tar -zxf mysql-5…