
freeCodeCamp 每日编程挑战 354从 sRGB 到 WCAG 对比度评级的完整算法实现【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp本篇围绕 freeCodeCamp 课程库中 JavaScript 每日编程挑战第 354 题Contrast Rating 3展开完整讲解从原始 RGB 值计算 WCAG 相对亮度含 sRGB 伽马校正、推导对比度比值并映射为 AAA/AA/Fail 评级的三步算法。读完你能掌握 WCAG 2.x 亮度模型的全部关键常数0.04045、12.92、2.4、0.2126/0.7152/0.0722、0.05的含义与实现细节并能独立通过全部 6 个断言测试。题目定位每日编程挑战中的第 354 题这道题定义在课程挑战文件中 6a22d77ddf034bc4e35b1d5b.mdfrontmatter 中标明challengeType: 28。从共享包的类型定义 challenge-types.ts 可以看到28对应dailyChallengeJs即 JavaScript 每日编程挑战类型其视图类型为classic经典代码编辑器视图提交方式为tests运行单元测试判定通过。该题同时登记在块结构文件 daily-coding-challenges-javascript.json 中排序于Challenge 353: Contrast Rating 2之后、Challenge 355: Morse Code之前。题目要求实现函数getContrastRating(rgb1, rgb2, isLargeText)rgb1、rgb2两个[R, G, B]整数数组取值 0~255isLargeText布尔值指示文本是否为大号文本返回值字符串AAA、AA或Fail。算法分两大阶段先把每个 RGB 值转换为相对亮度relative luminance再计算对比度比值并按阈值表定级。阶段一RGB 转相对亮度sRGB 伽马校正WCAG 的相对亮度不是 RGB 三通道的简单平均而是要先把显示设备使用的 sRGB 编码值还原为线性光强再加权求和。题目给出的完整步骤是归一化每个通道除以 255得到 0~1 之间的值逐通道伽马校正分支阈值 0.04045若通道值 0.04045channel / 12.92线性近似段否则((channel 0.055) / 1.055) ^ 2.4幂律段加权求和luminance 0.2126 * R 0.7152 * G 0.0722 * B。几个值得注意的实现细节阈值0.04045对应 sRGB 标准的分段点。对 8 位通道而言0.04045 * 255 ≈ 10.31也就是说原始值 0~10 的通道走线性段11 及以上走幂律段两种分支在实际输入中都会被触发权重0.2126 / 0.7152 / 0.0722之和恰好为 1因此纯白[255,255,255]的亮度恒为1.0纯黑[0,0,0]恒为0。人眼对绿色通道最敏感所以绿色的权重高达 0.7152边界条件用的是恰好等于 0.04045 的归一化值取线性段这与 WCAG 原文的措辞一致。阶段二对比度比值与评级的映射得到两个亮度l1、l2后对比度比值按如下公式计算ratio (l1 0.05) / (l2 0.05)题目明确了一个简化约定第一个参数rgb1始终是较亮的一方因此无需像通用 WCAG 公式那样做 max/min 处理。0.05的偏移保证了比值下限为 1两色相同时上限为 21纯白对纯黑1.05 / 0.05 21这也是 WCAG 比值 1:1 ~ 21:1 取值区间的来源。评级阈值表题目原文完整继承RatingNormal TextLarge TextAAA7.04.5AA4.53.0Failbelow 4.5below 3.0即普通文本要求 7.0才达 AAA、 4.5达 AA低于 4.5 判 Fail大号文本门槛降为 4.5AAA和 3.0AA。注意判断顺序必须先 AAA 后 AA——4.8 同时满足两个大号文本条件只有先判 AAA 才能返回正确等级。这道题是连续三题系列同一块中的 Challenge 352: Contrast Rating 1 与 Challenge 353: Contrast Rating 2的收官题352 题只做比值 → 评级的查表353 题做亮度 → 比值 → 评级354 题则把整条管线打通——从最原始的 RGB 输入一步到位。三个系列题共享同一套评级逻辑354 题的解法可以看作前两题解法的组合。官方参考解答与代码走读挑战的初始种子代码只有一个占位实现function getContrastRating(rgb1, rgb2, isLargeText) { return rgb1; }参考解答继承自挑战文件的# --solutions--段function getContrastRating(rgb1, rgb2, isLargeText) { function toLuminance([r, g, b]) { return [r, g, b].map(channel { channel channel / 255; return channel 0.04045 ? channel / 12.92 : ((channel 0.055) / 1.055) ** 2.4; }).reduce((sum, c, i) sum c * [0.2126, 0.7152, 0.0722][i], 0); } const l1 toLuminance(rgb1); const l2 toLuminance(rgb2); const ratio (l1 0.05) / (l2 0.05); if (isLargeText) { if (ratio 4.5) return AAA; if (ratio 3.0) return AA; } else { if (ratio 7.0) return AAA; if (ratio 4.5) return AA; } return Fail; }几个可借鉴的实现手法内联辅助函数toLuminance封装解构 → 归一化 → 伽马校正 → 加权求和全过程主流程保持三行两次亮度、一次比值、一次定级map处理逐通道校正reduce完成加权求和reduce的第三个参数i用于按下标取出权重数组[0.2126, 0.7152, 0.0722][i]避免了为 R/G/B 各写一条乘法幂运算使用**运算符ES2016((c 0.055) / 1.055) ** 2.4等价于Math.pow(...)写法阈值比较全部用浮点字面量直接判定ratio 4.5等。由于本题断言输入都远离边界值直接比较没有精度问题若用于生产环境处理任意浮点输入可考虑对ratio先做四舍五入再比较。用测试用例验证算法题目给出 6 条assert.equal断言覆盖普通/大号文本各三个等级assert.equal(getContrastRating([255, 255, 255], [0, 0, 0], false), AAA); assert.equal(getContrastRating([215, 188, 188], [55, 55, 55], false), AA); assert.equal(getContrastRating([143, 144, 210], [46, 47, 61], false), Fail); assert.equal(getContrastRating([167, 167, 210], [53, 10, 53], true), AAA); assert.equal(getContrastRating([135, 147, 155], [60, 70, 90], true), AA); assert.equal(getContrastRating([125, 210, 195], [105, 130, 90], true), Fail);以第一条为例手工演算可以验证公式自洽纯白[255, 255, 255]每通道255/255 1 0.04045走幂律段((1 0.055)/1.055)^2.4 1亮度0.2126*1 0.7152*1 0.0722*1 1.0纯黑[0, 0, 0]每通道0 0.040450/12.92 0亮度0比值(1.0 0.05)/(0 0.05) 21普通文本下21 7.0返回AAA。再看大号文本下的失败案例[125, 210, 195]vs[105, 130, 90]两色明度接近比值落在 3.0 之下即便放宽到大号文本门槛也只够Fail——这条用例提醒我们大号文本的 3.0 下限依然不可无视。挑战在 freeCodeCamp 管线中的位置从源码结构看这道题作为课程数据会被解析进挑战图tools/daily-challenges/目录下的 helpers.ts 通过 GraphQL 按superBlock: dev-playground与block: daily-coding-challenges-javascript过滤并按challengeOrder排序拉取挑战seed-daily-challenges.ts 则负责将种子数据写入数据库供今日挑战轮换使用挑战文件本身的字段如challengeType的合法取值范围 0~33由 challenge-schema.js 中的 Joi 模式校验28恰在允许区间内。小结这道 354 题的实质是把 WCAG 相对亮度模型压缩进约 20 行 JavaScript归一化 → 0.04045 分段伽马校正 → 0.2126/0.7152/0.0722 加权 →0.05比值 → 双档阈值定级。理解 0.04045分支的触发范围8 位输入的 0~10、权重之和为 1 带来的纯白/纯黑边界、以及先 AAA 后 AA的判断顺序是正确且高效实现的关键。完成它之后整条RGB → 亮度 → 比值 → 评级的无障碍算法管线就全部打通了。【免费下载链接】freeCodeCampfreeCodeCamp.orgs open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考