核心方案是用IntersectionObserver实现图片两阶段加载:先展示低分辨率像素化占位图,再异步加载高清图并平滑过渡;支持按dpr、网络状况和设备能力动态调整策略。

核心思路是:用 IntersectionObserver 检测图片是否进入视口,触发两阶段加载——先展示低分辨率像素化占位图(体积小、渲染快),再异步加载高清图并平滑过渡。整个过程不阻塞主线程,且能根据设备像素比(dpr)、网络状况或用户偏好动态调整占位图策略。
一、HTML 结构要支持分层加载
每张图片需携带三类信息:占位图地址、真实图地址、可选的加载提示逻辑。
- 用 src 加载轻量级像素化占位图(如 8×6 像素 GIF 或 base64 编码的极小图)
- 把高清图 URL 存在 data-src 中;若需响应式,可用 data-srcset + data-sizes
- 添加 data-dpr 或 data-priority 属性,供后续做自适应决策(比如 dpr=2 的设备优先加载 @2x 占位图)
二、IntersectionObserver 配置需兼顾精度与性能
默认阈值(0)可能过早触发加载,建议按场景微调:
- 首屏关键图:设 threshold: 0.1(露出 10% 就开始加载)
- 普通内容图:用 threshold: 0.25,避免滚动过快时误触发
- 为适配慢网用户,可结合 navigator.connection.effectiveType 动态降级:若为 '2g' 或 'slow-2g',提升 threshold 至 0.5,并跳过像素化过渡,直接淡入占位图
三、占位图切换需带状态控制与视觉反馈
不能简单替换 src,要确保过渡自然、可中断、可回退:
- 给 img 添加 class="pixel-loading",CSS 中定义:
img.pixel-loading { image-rendering: pixelated; transition: opacity 0.3s ease, transform 0.2s; } - 加载高清图前先加 opacity: 0.7 和轻微缩放(
transform: scale(0.98)),加载完成后再移除 class 并重置样式 - 监听 img.onload 和 img.onerror,失败时保留占位图并标记 class="load-failed",便于埋点或 fallback
四、进阶:按设备能力动态生成占位图
不硬编码占位图地址,而是运行时生成:
- 对支持 createImageBitmap 的浏览器,可在 JS 中将原图 canvas 缩小到 4×3 像素,再转成 blob URL 作为占位图
- 服务端可提供 /api/placeholder?w=4&h=3&hash=xxx 接口,返回对应尺寸的模糊块状图(带 cache-control)
- 利用 CSS container queries 或 matchMedia 判断容器宽度,决定是否启用像素化动画(小屏设备可跳过动画,只做淡入)

















