纯前端无法阻止投屏,防投屏水印仅通过canvas叠加用户ID、时间戳等干扰信息降低传播价值;CSS伪元素无效因投屏忽略外层容器,canvas需absolute定位、动态适配dpr、离屏绘制+requestAnimationFrame优化性能,并处理全屏剥离问题。

纯前端无法阻止投屏,所谓“防投屏水印”只是让投屏画面带干扰性标识——它不拦住投屏行为,但让截下来的视频/录屏内容明显带用户 ID、时间戳和错位文字,失去传播价值。
video 元素上叠加 canvas 水印为什么比 CSS 伪元素更有效
CSS 伪元素(如 ::before)加在 <video></video> 外层容器上,会被系统投屏直接忽略;而用 canvas 绘制后盖在 video 上层,并设 pointer-events: none,能确保水印像素真正参与渲染管线——哪怕投屏,只要浏览器把这层 canvas 当作可见内容合成进去,水印就跟着走。
- 必须用
position: absolute+z-index把 canvas 叠在video的同一 stacking context 内,不能靠父级 fixed 定位“飞出去” - 监听
video的loadedmetadata和resize事件重设 canvas 尺寸,否则高清屏下拉伸失真 - 避免用
transform: scale()缩放 canvas,会触发新 layer,导致投屏时水印被裁或偏移
drawImage + requestAnimationFrame 实现低卡顿动态水印
直接在 canvas 上每帧 fillText 画文字,高频率重绘会导致 video 播放掉帧。更稳的做法是:先用离屏 canvas 绘好带倾斜、透明、随机偏移的水印图案,再用 drawImage 每帧贴图过去。
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 主 canvas 每次只执行
ctx.drawImage(offscreenCanvas, 0, 0),开销极小 - 离屏 canvas 仅在用户信息变更(如登录态刷新)或窗口 resize 时重建
- 用
requestAnimationFrame而非setInterval,与视频播放节奏同步,减少撕裂感 - 务必调用
ctx.clearRect(0, 0, width, height)再 drawImage,否则残留旧帧造成重影
移动端 video 全屏时水印消失?检查这三点
iOS Safari 和部分安卓浏览器进入原生全屏后,会把 video 提升到独立 surface 渲染,DOM 层 canvas 自动被剥离——此时水印必然消失,无通用绕过方案。
- 优先用
webkit-playsinline+playsinline属性禁用原生全屏,强制内联播放(需服务端配置 MIME 类型支持) - 若必须支持原生全屏,可在退出全屏回调里立即重建 canvas 并重绘,至少保证恢复后有水印
- Android WebView 中,确认未启用
setMediaPlaybackRequiresUserGesture(true),否则 canvas 绘制可能被静音策略阻断
最易被忽略的是 devicePixelRatio 动态适配:不乘 dpr 直接用 window.innerWidth 设 canvas.width,高清屏下水印细得看不见;但乘了 dpr 又不调用 ctx.scale(dpr, dpr),文字会糊成一片——这两步必须成对出现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










