揭秘Canvas挖空遮罩技巧:Fokus如何实现聚光灯式文字高亮的核心原理

揭秘Canvas挖空遮罩技巧:Fokus如何实现聚光灯式文字高亮的核心原理 揭秘Canvas挖空遮罩技巧Fokus如何实现聚光灯式文字高亮的核心原理【免费下载链接】Fokus项目地址: https://gitcode.com/gh_mirrors/fo/FokusFokus是一个仅约 3kb、零依赖的 JavaScript 文字高亮库你在页面上选中任意一段文字它立刻用一层半透明黑色的Canvas 挖空遮罩盖住其余页面就像舞台聚光灯打在选区上。这篇文章就用它不到 400 行的源码拆解这个黑布挖洞聚光灯效果的完整实现原理看完你也能举一反三做出类似效果。 先看效果Fokus 是什么Fokus 的使用体验非常简单粗暴打开演示页 index.html页面上加载了核心脚本 js/fokus.js用鼠标选中任意一段文字支持鼠标和键盘选择整个页面唰地变暗只有选中的文字区域保持明亮清晰整个过程没有引入任何外部资源压缩后的 js/fokus.min.js 只有 3.5kb比一张头像图片还小。那么问题来了一张全黑半透明的幕布中间为什么会自动出现一个透明的洞洞的形状又是如何跟住你的选区的答案就是今天要揭秘的主角——Canvas 挖空遮罩技巧。 核心原理一句话先涂黑整屏再擦掉选区传统做法要在选区上下左右各放一个 div 拼出边框遇到跨段落选区会非常痛苦。而 Fokus 的思路完全反过来遮罩不是围绕选区画的而是画满全屏再挖掉选区。具体分三步全部发生在 js/fokus.js 的redraw()函数中步骤操作作用第 1 步clearRect清空画布准备一块干净的幕布第 2 步fillStyle rgba(0,0,0,α)fillRect铺满全屏整页变暗α 由 0 渐增到 0.75第 3 步对选区矩形再调一次clearRect把选区擦成透明文字露出来关键点在于Canvas 的clearRect不是画一个洞而是把该区域像素擦回透明。当这块画布悬浮在整个页面最上层时被擦掉的地方正好透出底下的文字——聚光灯效果就此诞生。核心逻辑浓缩起来只有两行// 涂黑整屏alpha 决定幕布黑度 ctx.fillRect(0, 0, overlay.width, overlay.height); // 再擦掉选区矩形露出底下的文字 ctx.clearRect(x, y, w, h);是不是比想象中简单得多✨ 画布如何做到悬浮在页面上方、又不挡住鼠标在初始化函数 initialize() 中Fokus 创建了一个canvas元素并做了两件神来之笔的配置position: fixedzIndex: 2147483647画布固定钉在视口上、层级拉到 CSS 允许的最大值保证永远盖住一切内容pointerEvents: none让画布对鼠标事件视而不见用户选文字、点链接照常操作完全感知不到它存在另外窗口尺寸变化时会同步重置画布的宽高见 onWindowResize所以遮罩永远和视口等大不会出现黑布跟不上浏览器的尴尬。 选区坐标从哪来——DOM 树遍历 偏移量累加洞的位置取决于选区矩形的坐标。Fokus 的取数流程是这样的拿选区节点通过浏览器原生window.getSelection()获取当前选区再用nextNode()沿 DOM 树从起点走到终点收集覆盖到的所有节点getSelectedNodes算屏幕坐标getScreenPosition()从节点沿offsetParent链一路向上累加offsetLeft/offsetTop得到绝对位置源码位置并成一个大矩形遍历所有节点用Math.min/max求出包围它们的左上角与右下角updateSelection这样无论选区跨多少行、跨几个p最后都能归并成一个规整的矩形洞。同时它还过滤了 0 宽高元素和br避免空选区触发遮罩。 为什么动画丝滑rAF 循环 双重缓动Fokus 的高级感来自 redraw() 用requestAnimationFrame驱动的动画循环里面有两条独立的渐近线透明度缓动有选区时alpha每帧向 0.75 靠近 8%页面渐暗取消选择时则快速衰减归零位置缓动洞的位置每帧向目标选区靠近 18%线性插值拖动鼠标扩展选区时洞会像有阻尼一样平滑地追上去这就是为什么选区变化时遮罩不是生硬跳变而是带着轻微的跟随惯性——一行插值公式换来的质感。选区消失、透明度归零后画布会被直接从 DOM 移除不占用任何渲染开销。 一分钟跑起来想要亲手把玩克隆仓库后打开演示页即可git clone https://gitcode.com/gh_mirrors/fo/Fokus然后用浏览器打开Fokus/index.html选中页面上任意文字感受这个 3kb 小库带来的聚光灯瞬间。更多背景信息可阅读 README.md 与 LICENSE。 小结这个 3kb 项目教会我们的反直觉的解法遇到给内容加边框式强调时不妨想想盖住全局、挖空局部Canvas 挖空遮罩比堆 div 干净得多fillRectclearRect的组合拳涂色再擦除是 Canvas 上实现镂空、挖洞、蒙版类效果的万能公式pointer-events: none是悬浮层的标配让视觉层与交互层解耦rAF 线性插值低成本实现专业级缓动动画的通用套路下次你想给自己的博客加一个选中即高亮的聚光灯体验时不妨直接参考 js/fokus.js 里这套 Canvas 挖空遮罩的实现思路——毕竟优雅的效果往往来自最朴素的画布操作。【免费下载链接】Fokus项目地址: https://gitcode.com/gh_mirrors/fo/Fokus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考