Bilibili-Evolved 高分辨率图片组件(imageResolution)深度解析:DPI 缩放下的图片源替换原理与配置指南
【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved
导读
「高分辨率图片」是 Bilibili-Evolved 内置的实用工具类组件,其核心职责是:当屏幕 DPI 缩放超过 200% 时,自动将哔哩哔哩页面中按@xxxw/@xxxw_xxh规则裁剪缩略的图片替换为更高分辨率的图片源,从而让高分屏用户获得清晰的浏览体验。本文以组件文档 image-resolution/index.md 为骨架,结合源码逐层讲解其工作流程、缩放算法、两个配置选项的语义,以及加载变慢、图片闪动、比例失衡等已知问题的成因与规避方法,帮助你正确启用与调优该组件。
一、组件定位:为什么需要"高分辨率图片"
哔哩哔哩的图片服务(如头像、封面、动态配图)在绝大多数场景下都会返回经过尺寸裁剪的缩略图,URL 中携带形如@672w_378h或@96w的缩放后缀。在普通屏幕上这些缩略图足够清晰,但在 Retina 屏、4K 屏等高 DPI 设备上,系统会以高于 1 的逻辑像素比(devicePixelRatio)渲染页面,缩略图被放大后就会出现明显的模糊。
「高分辨率图片」组件正是针对这一痛点:当屏幕 DPI 缩放超过 200%(即devicePixelRatio > 2)时,按比例放大 URL 中的尺寸参数,向 CDN 请求更高分辨率的图片源。
从组件元数据(index.ts)可以看到其默认行为:
- 组件名
imageResolution,显示名「高分辨率图片」,归属utils(实用工具)标签; enabledByDefault: window.devicePixelRatio > 1,即只要 DPR 大于 1(任何高分屏)默认即启用;- 入口为
startResolution,选项包含scale与originalImageInArticles。
二、工作原理:从图片 URL 重写到底层实现
2.1 哔哩哔哩图片 URL 的尺寸规则
B 站图片地址中,@符号后的部分即为尺寸指令,常见两种形态:
@200w:仅指定宽度,高度按原图比例自动计算;@200w_112h:同时指定宽度与高度。
源码中的匹配正则(resolution.ts)正是针对这一约定:
const resizeRegex = /@(\d+)Ww[Hh])?/替换时,若原 URL 只有宽度,则新 URL 写为@${newWidth}w;若宽高都有,则写为@${newWidth}w_${newHeight}h。当计算出的新尺寸为无穷大(请求原图)时,则直接把@...后缀整体移除,等价于请求原始分辨率图片。
2.2 整体流程
组件入口startResolution(resolution.ts)通过styledComponentEntry包装(见 styled-component.ts),先动态注入样式文件 fix.scss,再执行主逻辑:
- 计算缩放倍率:读取
scale选项,auto时调用getAutoScale(),否则解析为数字; - 全量扫描:用
document.createNodeIterator(walk函数)遍历document.body下所有元素,逐一调用imageResolution处理; - 动态监听:注册
allMutations(基于MutationObserver,见 observer.ts),对后续新增节点(如滚动加载的图片)递归执行同样的替换,保证动态内容也被覆盖。
2.3 auto 缩放倍率的算法
getAutoScale()(resolution.ts)逻辑非常简洁:
const getAutoScale = () => { if (window.devicePixelRatio <= 2) { return 1 } return window.devicePixelRatio / 2 }- DPR ≤ 2(即 200% 缩放下限之内)时倍率为 1,不做任何替换(
scale === 1时入口函数直接 return,见第 135-137 行),避免低缩放屏幕上的无谓开销; - DPR > 2 时取
DPR / 2,例如 DPR = 2.5(250% 缩放)时请求 1.25 倍,DPR = 3(300% 缩放)时请求 1.5 倍。这与文档中"250% 的缩放下会请求 1.5 倍尺寸的图片"略有出入——文档示例按"超出 200% 的比例"理解,而源码实现实际按DPR / 2计算,两者在 DPR = 3 时(1.5 倍)是一致的。以当前仓库源码为准:实际倍率 =devicePixelRatio / 2。
2.4 图片源的三类替换通道
imageResolution函数(resolution.ts)对每个元素同时处理三种图片来源,并通过attributes监听(observer.ts)在属性变化时再次替换:
src属性(<img>标签);srcset属性(响应式图片集合);style.backgroundImage(CSS 背景图)。
替换前有一系列守卫条件:
- 排除选择器:
#certify-img1、#certify-img2(认证图片)不处理; - 含逗号的 srcset 不处理:
value.includes(',')时直接跳过,避免破坏多候选源语法; - 去重防抖:通过
data-resolution-width自定义属性记录已替换的宽度,若当前宽度不大于已记录值则跳过,防止重复放大导致图片被无限放大; - 匹配失败(URL 中无
@...w规则)直接跳过。
2.5 关键修复:替换图片源后的尺寸比例处理
文档特别提醒:"由于 b 站在很多地方没有设置图片维持原比例,如果计算后的图片尺寸超出原图尺寸则会产生错误的比例"。
源码对此做了针对性处理:当元素原本没有显式width/height属性时(resolution.ts),会按选择器类别补写属性以锁定布局:
.bili-avatar-img(动态头像框):只设置height,对应 issue #2030;.logo-img(首页 Logo):width和height都设置,对应 issue #4480;- 其余元素:只设置
width,由浏览器按原图比例推导高度。
同时,fix.scss 用 CSS 兜底修复了收藏夹封面(favInfo-box)与评论区"航海"挂件图片的宽度/对齐问题,避免替换后布局错乱。
三、配置选项详解
组件共两个选项,定义于 index.ts,并通过defineOptionsMetadata注册(见 define.ts)。
3.1scale(缩放级别,默认auto)
文档给出的取值有两类:
| 取值 | 含义 | 行为 |
|---|---|---|
auto | 自动模式 | 按devicePixelRatio / 2计算倍率(DPR ≤ 2 时为 1,不替换) |
数字(如1.2、1.5、2) | 自定义倍率 | 以该数字作为统一缩放倍率,源码中通过parseFloat解析 |
数字模式不受 DPR 约束,适合想强制放大、或反过来手动降低缩放级别的用户。文档明确指出:当自动计算出的图片尺寸超出原图尺寸、导致页面出现错误比例时,可在选项中手动调低缩放级别来规避。
3.2originalImageInArticles(在专栏中请求原图,默认false)
该选项针对专栏文章页:开启后,命中.article-detail .article-content img选择器的图片,其缩放倍率被设为Infinity(见 resolution.ts),从而在 URL 替换时直接去掉@...尺寸后缀,请求原始分辨率的图片,保证长文配图的最佳清晰度。代价是加载流量与时间显著增加,因此默认关闭,需要用户按需开启。
四、已知问题与使用注意事项
文档明确列出了该组件带来的副作用,使用时应充分权衡:
- 加载时间变长:高分辨率图片体积更大,CDN 传输与解码耗时随之增加;
- 图片闪动:部分浏览器中,由于本质上是"更换图片源",
src被重写后图片会重新加载,出现短暂闪烁。这是源码层面setAttribute('src', ...)直接换源的必然结果,无法完全消除,只能通过降低倍率减少触发; - 比例错误:B 站大量位置未设置图片维持原比例(
object-fit等),一旦放大后的尺寸超过原图尺寸,会拉伸变形。应对手段有三:手动调低scale、依赖 2.5 节所述的属性补写逻辑、以及fix.scss中的样式兜底; - DPI 判断边界:DPR ≤ 2 的屏幕默认不替换(auto 模式下倍率为 1),因此普通 100%/125%/150%/200% 缩放下该组件实际不生效,仅在超 200% 缩放时才工作。
五、源码结构速查
| 文件 | 作用 |
|---|---|
| image-resolution/index.md | 组件使用文档(本文依据) |
| image-resolution/index.ts | 组件元数据与选项定义 |
| image-resolution/resolution.ts | 核心实现:URL 正则重写、DOM 遍历、MutationObserver 监听 |
| image-resolution/fix.scss | 替换后的布局修复样式 |
| styled-component.ts | styledComponentEntry工具:动态注入样式后执行入口 |
| observer.ts | attributes/allMutations观察器,驱动动态内容替换 |
结语
「高分辨率图片」组件通过一套极轻量的 URL 重写机制(正则匹配@w/@w_h后缀 → 按 DPR 计算倍率 → 重写src/srcset/backgroundImage),配合 DOM 遍历与 MutationObserver,在保持页面布局稳定的前提下为高分屏用户提供更清晰的图片。理解其auto倍率算法(DPR / 2)、originalImageInArticles的原图直取语义,以及比例修复策略,是正确配置该组件、规避图片闪动与比例失真问题的关键。
【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考