首页 > 网页制作 >自定义光标与动态聚光灯效果的纯CSS+JS教程

自定义光标与动态聚光灯效果的纯CSS+JS教程

来源:互联网 2026-07-14 08:25:11

利用CSS径向渐变与伪元素创建黑底透光遮罩,通过JavaScript动态更新CSS自定义变量控制光斑位置,实现鼠标跟随聚光灯效果,避免频繁DOM操作,性能更优,精准揭示底层内容。

本文详解如何用 CSS radial-gradient 配合 CSS 变量和伪元素,创建可随鼠标移动、精准居中且真正“揭示内容”的聚光灯效果,避免 DOM 操作性能损耗。

如果你曾被那种仅叠加一个发光圆、却无法穿透遮罩显示内容的“伪聚光灯”坑过,那么这篇文章将帮你解决真正的问题。核心思路并不复杂:使用 CSS 的 radial-gradient 配合伪元素,构建一个“黑底+中心透光”的遮罩层,然后通过动态更新 background-position 让光斑跟随鼠标移动。直接插入一个

并设置径向渐变背景,本质上只是在顶层画了一个圆,根本无法穿透遮罩去显示底层内容——这才是问题的关键。

正确做法是:利用 .box::before 伪元素充当全屏遮罩层,其背景为“中心透明 → 外圈全黑”的径向渐变;再通过 JavaScript 实时更新 --flashlight-x-pos--flashlight-y-pos 两个 CSS 自定义变量,驱动背景定位,使“光洞”始终对准鼠标位置。

长期稳定更新的攒劲资源: >>>点此立即查看<<<

下面直接上步骤。

1. HTML 结构(极简)

Light

2. CSS 样式(核心遮罩逻辑)

.box {
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: none;
  width: 100%;
  padding: 5rem;
  background-color: #000;
  overflow: hidden;
  position: relative;
  /* 初始光斑偏移至可视区外,实现“隐藏”效果 */
  --flashlight-x-pos: -200px;
  --flashlight-y-pos: -200px;
  --flashlight-inset: -300px; /* 控制遮罩层大小,确保完全覆盖 */
}
/* 聚光灯遮罩层(伪元素) */
.box::before {
  content: '';
  position: absolute;
  inset: var(--flashlight-inset); /* 全向扩展遮罩 */
  background-image: radial-gradient(
    circle,
    transparent 0%,     /* 中心完全透明 → 显示内容 */
    rgba(0, 0, 0, 0.8) 60px,  /* 过渡到半透明灰黑 */
    #000 70px,         /* 快速过渡为纯黑 */
    #000 100%           /* 完全覆盖 */
  );
  background-position: var(--flashlight-x-pos) var(--flashlight-y-pos);
  background-repeat: no-repeat;
  z-index: 1;
}
/* 自定义光标(也用伪元素,减少 DOM 节点) */
.box::after {
  content: '';
  position: absolute;
  width: 50px;
  height: 50px;
  background: url('https://picsum.photos/50') no-repeat center / contain;
  transform: translate(var(--flashlight-x-pos), var(--flashlight-y-pos));
  pointer-events: none;
  z-index: 2;
}

3. JavaScript(高效定位 + 变量驱动)

const box = document.querySelector('.box');
//  关键:getBoundingClientRect 在事件外计算一次,避免 mousemove 中重复调用(性能敏感!)
const rect = box.getBoundingClientRect();
box.addEventListener('mousemove', (e) => {
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  // 计算相对于容器中心的偏移量(使光斑自然居中)
  box.style.setProperty('--flashlight-x-pos', `${x - rect.width / 2}px`);
  box.style.setProperty('--flashlight-y-pos', `${y - rect.height / 2}px`);
});
box.addEventListener('mouseleave', () => {
  // 鼠标离开时,将光斑移出视区,实现平滑隐藏
  box.style.setProperty('--flashlight-x-pos', '-300px');
  box.style.setProperty('--flashlight-y-pos', '-300px');
});

关键优势说明:

  • 真揭示效果.box::before 的黑色遮罩层加上中心透明区域,天然支持“透过光洞看到下方

    ”,完全不需要额外图层叠加。

  • 高性能:不用频繁 appendChildstyle.left/top 操作,只更新 CSS 变量,浏览器自己就能优化渲染。
  • 响应式友好background-position 会自动适配缩放与滚动,完全不用重算坐标。
  • 可定制性强:修改 radial-gradient 的参数,即可调整光斑大小、边缘柔硬度、遮罩深浅(比如 rgba(0,0,0,0.9) 会更暗)。

注意事项:

  • 确保 .box 有明确的尺寸(比如 width/heightpadding),否则 getBoundingClientRect() 的返回值可能不稳定。
  • 如果页面存在滚动,需要监听 scroll 并重新计算 rect,或者改用 e.offsetX/e.offsetY(但兼容性略低)。
  • 自定义光标图片建议用 background-image 而不是 标签,避免 pointer-events: none 导致的点击穿透问题。

这样一来,你就能得到一个轻量、流畅、语义清晰的聚光灯交互效果——它不只是视觉装饰,而是真正能“照亮并揭示内容”的实用 UI 组件。

侠游戏发布此文仅为了传递信息,不代表侠游戏网站认同其观点或证实其描述

热游推荐

更多
湘ICP备14008430号-1 湘公网安备 43070302000280号
All Rights Reserved
本站为非盈利网站,不接受任何广告。本站所有软件,都由网友
上传,如有侵犯你的版权,请发邮件给xiayx666@163.com
抵制不良色情、反动、暴力游戏。注意自我保护,谨防受骗上当。
适度游戏益脑,沉迷游戏伤身。合理安排时间,享受健康生活。