如何在HTML/CSS/JS中用对象作为遮罩实现标题颜色反转?
实现气泡过标题时颜色反转的效果
核心思路验证
你提到的三层结构思路完全可行,核心逻辑就是通过分层显示实现局部颜色反转:
- 底层:深色标题(如黑色文字),
z-index最低 - 中间层:紫色气泡,作为视觉遮罩的参照
- 顶层:浅色标题(如白色文字),仅在气泡覆盖区域显示,形成“反转”视觉效果
具体实现方案
1. 三层结构+动态遮罩实现(精准匹配需求)
HTML结构
<div class="title-wrapper"> <!-- 底层深色标题 --> <h1 class="title title-dark">Bubble Reveal</h1> <!-- 气泡容器 --> <div class="bubble-container"> <div class="bubble"></div> <div class="bubble"></div> </div> <!-- 顶层浅色标题 --> <h1 class="title title-light">Bubble Reveal</h1> </div>
CSS基础样式
.title-wrapper { position: relative; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; background: #fff; } .title { position: absolute; font-size: 5rem; margin: 0; font-weight: bold; } .title-dark { color: #000; z-index: 1; } .title-light { color: #fff; z-index: 3; /* 初始遮罩为空,不显示 */ mask: none; -webkit-mask: none; } .bubble-container { position: absolute; z-index: 2; width: 100%; height: 100%; pointer-events: none; /* 避免气泡阻挡页面交互 */ } .bubble { position: absolute; width: 100px; height: 100px; border-radius: 50%; background: #9333ea; /* 紫色气泡 */ top: 50%; left: 50%; transform: translate(-50%, -50%); }
JavaScript动态控制遮罩
实时跟踪气泡位置,更新顶层标题的遮罩范围,只显示气泡覆盖区域:
const lightTitle = document.querySelector('.title-light'); const bubbles = document.querySelectorAll('.bubble'); const container = document.querySelector('.title-wrapper'); function updateTitleMask() { let maskPaths = []; bubbles.forEach(bubble => { const bubbleRect = bubble.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); // 计算气泡相对于容器的中心坐标和半径 const centerX = bubbleRect.left - containerRect.left + bubbleRect.width / 2; const centerY = bubbleRect.top - containerRect.top + bubbleRect.height / 2; const radius = bubbleRect.width / 2; // 生成圆形遮罩路径 maskPaths.push(`circle(${radius}px at ${centerX}px ${centerY}px)`); }); // 合并所有气泡的遮罩路径 const maskValue = maskPaths.join(', '); lightTitle.style.mask = maskValue; lightTitle.style.webkitMask = maskValue; } // 气泡移动动画 function animateBubbles() { bubbles.forEach(bubble => { // 随机移动速度和方向 const speedX = (Math.random() - 0.5) * 3; const speedY = (Math.random() - 0.5) * 3; setInterval(() => { let currentTop = parseFloat(bubble.style.top) || 50; let currentLeft = parseFloat(bubble.style.left) || 50; currentTop += speedY; currentLeft += speedX; // 边界检测,防止气泡移出屏幕 currentTop = Math.max(0, Math.min(100, currentTop)); currentLeft = Math.max(0, Math.min(100, currentLeft)); bubble.style.top = `${currentTop}%`; bubble.style.left = `${currentLeft}%`; // 实时更新遮罩 updateTitleMask(); }, 16); // 维持60fps动画流畅度 }); } // 启动动画 animateBubbles();
2. 混合模式简化方案(代码更简洁)
如果不需要极致精准的颜色控制,可以用mix-blend-mode: difference直接实现颜色反转,省去遮罩逻辑:
<div class="container"> <h1 class="title">Bubble Reveal</h1> <div class="bubble-container"> <div class="bubble"></div> <div class="bubble"></div> </div> </div>
.container { position: relative; width: 100vw; height: 100vh; display: flex; align-items: center; justify-content: center; background: #000; } .title { font-size: 5rem; color: #fff; z-index: 1; } .bubble-container { position: absolute; width: 100%; height: 100%; z-index: 2; pointer-events: none; } .bubble { position: absolute; width: 100px; height: 100px; border-radius: 50%; background: #9333ea; mix-blend-mode: difference; /* 核心混合模式 */ top: 50%; left: 50%; transform: translate(-50%, -50%); }
这种方式利用混合模式的颜色计算自动实现反转,代码更简洁,但颜色效果由混合规则决定,需要根据需求调整基础色值。
内容的提问来源于stack exchange,提问作者GawronDev
相关产品推荐
相关产品推荐

