如何实现文字常态渐变+鼠标悬浮单个字母显示30px圆形渐变效果?
问题描述
- 需求场景:
- 常态(未悬浮)下文字采用渐变色彩
- 鼠标悬浮任意字母时,该字母区域显示30px*30px的圆形渐变,渐变规则为
linear-gradient(180deg, rgba(255, 33, 44, 0.5) 0%, rgba(25, 50, 25, 0.3) 100%)
- 当前遇到的问题:
- 若将圆形的
fill设为transparent,鼠标事件会失效 - 文字常态使用渐变后,悬浮时无法触发颜色变化
- 若将圆形的
当前实现的问题分析
- 鼠标事件失效原因:
.cursor设置了pointer-events: none,导致自定义光标元素完全无法接收鼠标事件;同时如果将圆形fill设为transparent,SVG元素会失去可交互的点击区域。 - 悬浮无反应原因:当前代码未给单个字母绑定hover事件,且文字使用
background-clip: text后,直接修改color无法生效,自定义光标与文字的交互逻辑也未关联。
解决方案
核心思路
- 将每个字母拆为独立
<span>,实现精准的hover监听 - 用极低透明度填充替代
transparent,既保证视觉透明,又保留鼠标交互区域 - 通过切换自定义光标的类名来触发圆形渐变效果,同时可同步调整文字渐变
修改后的完整代码
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.20.3/TweenMax.min.js"></script> <div class="cursor"> <div class="cursor__ball cursor__ball--big"> <svg height="30" width="30"> <!-- 定义悬浮时的渐变 --> <defs> <linearGradient id="hoverGradient" x1="0%" y1="0%" x2="0%" y2="100%"> <stop offset="0%" style="stop-color:rgba(255,33,44,0.5);stop-opacity:1" /> <stop offset="100%" style="stop-color:rgba(25,50,25,0.3);stop-opacity:1" /> </linearGradient> </defs> <circle cx="15" cy="15" r="12" stroke-width="0"></circle> </svg> </div> </div> <div class="myText"> <h1> <span class="color-letter">G</span> <span class="color-letter">e</span> <span class="color-letter">t</span> <span class="color-letter"> </span> <span class="color-letter">t</span> <span class="color-letter">o</span> <span class="color-letter"> </span> <span class="color-letter">k</span> <span class="color-letter">n</span> <span class="color-letter">o</span> <span class="color-letter">w</span> <span class="color-letter"> </span> <span class="color-letter">m</span> <span class="color-letter">o</span> <span class="color-letter">r</span> <span class="color-letter">e</span> <span class="color-letter"> </span> <span class="color-letter">a</span> <span class="color-letter">b</span> <span class="color-letter">o</span> <span class="color-letter">u</span> <span class="color-letter">t</span> </h1> </div>
CSS
body { height: 100vh; background: #010101; cursor: none; margin: 0; display: flex; font-family: monospace; align-items: center; justify-content: center; } body .cursor { z-index: 999; } body .cursor__ball { position: fixed; top: 0; left: 0; z-index: 1000; } body .cursor__ball circle { /* 极低透明度填充,保证鼠标事件可触发 */ fill: rgba(0,0,0,0.01); } /* 悬浮字母时的光标渐变样式 */ body .cursor__ball--hover circle { fill: url(#hoverGradient); } body .myText { height: 100%; width: 100%; display: flex; justify-content: center; align-items: center; z-index: 1001; /* 确保文字能触发hover事件 */ } body .myText h1 { font-size: 80px; margin: 0; } body .myText h1 .color-letter { opacity: 0.8; background: linear-gradient(180deg, rgba(26, 33, 44, 0.5) 0%, rgba(255, 255, 255, 0.3) 100%); background-clip: text; -webkit-background-clip: text; position: relative; color: transparent; transition: all 0.3s ease; display: inline-block; /* 确保单个字母能接收鼠标事件 */ }
JS
const bigBall = document.querySelector(".cursor__ball--big"); const letters = document.querySelectorAll(".color-letter"); // 移动光标 document.body.addEventListener("mousemove", onMouseMove); function onMouseMove(e) { TweenMax.to(bigBall, 0.4, { x: e.pageX - 15, y: e.pageY - 15, }); } // 绑定单个字母的hover事件 letters.forEach(letter => { letter.addEventListener("mouseenter", () => { bigBall.classList.add("cursor__ball--hover"); // 可选:同步修改文字渐变 letter.style.background = "linear-gradient(180deg, rgba(255,255,255,0.8) 0%, rgba(26,33,44,0.6) 100%)"; letter.style.backgroundClip = "text"; letter.style.webkitBackgroundClip = "text"; }); letter.addEventListener("mouseleave", () => { bigBall.classList.remove("cursor__ball--hover"); // 恢复原文字渐变 letter.style.background = "linear-gradient(180deg, rgba(26, 33, 44, 0.5) 0%, rgba(255, 255, 255, 0.3) 100%)"; letter.style.backgroundClip = "text"; letter.style.webkitBackgroundClip = "text"; }); });
关键说明
- 用
rgba(0,0,0,0.01)替代transparent,既视觉透明又保留SVG的鼠标交互区域 - 拆分字母为独立
<span>,实现精准的hover触发 - 通过SVG的
<defs>定义渐变,避免重复代码;也可将光标改为div,直接用CSS背景渐变实现 - 调整
z-index确保文字能触发hover事件,同时光标显示在文字上方
内容的提问来源于stack exchange,提问作者h.m.p.frontendDeveloper
相关产品推荐
相关产品推荐

