html5 核心 api 存在被低估的实用能力:canvas drawimage 支持视频帧绘制但需处理跨域与状态;indexeddb 版本号必须显式递增才能触发升级;web workers 可用 cache api 离线存储;intersectionobserver rootmargin 不支持百分比。

HTML5 引擎本身没有“隐藏功能”——所谓“隐藏”,其实是标准 API 被低估、误用或浏览器实现差异导致的实用能力被忽略。
Canvas 2D 的 drawImage 支持视频帧直接绘制,但需注意跨域限制
很多开发者以为 drawImage 只能画 Image 或另一个 canvas,其实它也接受 HTMLVideoElement。这是做实时截图、简易录屏、滤镜预览的基础。
容易踩的坑:
- 视频未设置
crossOrigin="anonymous",会导致 canvas 被污染,后续调用toDataURL或getImageData报错SecurityError: The canvas has been tainted by cross-origin data - 视频尚未进入
loadeddata或canplay状态就调用drawImage,可能画出黑帧或空白 - 部分安卓 WebView 对
video.currentTime设置后立即 draw 不稳定,建议加requestAnimationFrame延迟一帧
IndexedDB 的 open 方法第二个参数是版本号,不是可选参数
很多人写成 indexedDB.open("db"),以为能自动兼容旧版结构。实际不传版本号时,浏览器按当前已存在数据库版本打开,onupgradeneeded 根本不会触发——哪怕你改了 objectStore 结构。
立即学习“前端免费学习笔记(深入)”;
正确做法:
- 每次修改 schema(增删 store、index、字段)都必须显式递增版本号:
indexedDB.open("db", 2) - 版本号只能是正整数,不能是字符串或小数;v1 → v2 可以,v1 → v1.5 会静默失败
- 多标签页同时 open 同名 DB 时,低版本 open 请求会被挂起,直到高版本完成 upgrade,这点常被忽略导致初始化卡顿
Web Workers 中无法访问 localStorage 和 document,但可用 cacheStorage 做离线数据桥接
Worker 里拿不到 DOM 或同步存储,但可以调用 caches.open() 读写 Cache API。这在预加载资源、后台解码、或配合 Service Worker 做数据预热时很实用。
关键细节:
-
caches是 Promise API,必须 await 或用.then(),不能同步读取 - Cache 名称区分大小写,
"my-cache"和"My-Cache"是两个独立缓存 - Chrome 90+ 开始,
caches.keys()在非安全上下文(http://)下被禁用,本地开发务必用localhost或 https - 不要把敏感数据放 cache,它不像
localStorage有同源隔离强度,且可通过 DevTools → Application → Cache Storage 直接查看
IntersectionObserver 的 rootMargin 支持 CSS 长度单位,但百分比值无效
rootMargin: "100px 0px" 可以提前触发懒加载,但写成 "100% 0px" 会静默退化为 "0px" —— 浏览器根本不支持百分比。
实操建议:
- 想实现“视口高度 20% 处触发”,得用 JS 动态算像素值:
const margin = window.innerHeight * 0.2 + "px" -
threshold接受数组,比如[0, 0.25, 0.5, 0.75, 1],能更精细控制回调时机,避免只靠 0/1 二值判断带来的抖动 - 在 iOS Safari 15.4 之前,
rootMargin对position: fixed元素计算有偏差,建议升级或 fallback 到 scroll 事件监听
这些不是什么“高级技巧”,而是日常写 HTML5 应用时,翻文档两遍、查 MDN 示例三次、再看几眼 Chrome DevTools 的 Console 错误才真正吃透的点。越基础的 API,越容易因为“看起来简单”而掉进实现细节的坑里。











