头像为什么总是糊的:128px 与 devicePixelRatio
本文最后更新于26 天前,其中的信息可能已经过时,如有错误请发送邮件到 [email protected]

用户上传头像,代码是这样的:

var n = 128;
var c = document.createElement('canvas');
c.width = n; c.height = n;
// 居中裁剪后画进去
var data = c.toDataURL('image/png');

页面里头像的 CSS 尺寸是:

#av{ width:96px; height:96px; border-radius:50%; object-fit:cover; }

看起来很合理:128px 的图显示在 96px 的框里,还留了余量。

漏算了一个东西

96px 是 CSS 像素。手机上还有 devicePixelRatio:

| 设备 | DPR | 96 CSS px 实际需要 | |—|—|—| | 普通屏 | 1 | 96 × 96 | | Retina | 2 | 192 × 192 | | 多数安卓旗舰 | 3 | 288 × 288 |

128px 的源图放在 288 个物理像素的位置上,就是被拉伸了 2.25 倍——必然糊。

改成 384

var n = 384;                       // 96px × 4,任何 DPR 都够
ctx.fillStyle = '#fff';            // JPEG 不支持透明,先铺白底
ctx.fillRect(0, 0, n, n);
ctx.drawImage(img, sx, sy, s, s, 0, 0, n, n);
var data = c.toDataURL('image/jpeg', 0.92);

为什么用 JPEG 而不是 PNG:384 的 PNG 动辄 300KB+,JPEG q0.92 通常只有 30–80KB,画质差距肉眼几乎看不出。

铺白底这一步不能省。透明 PNG 转 JPEG 时,透明区域会变成黑色,头像会出现一圈黑边。

QQ 头像的另一个坑

第三方返回的头像字段有讲究:

  • figureurl — 30×30
  • figureurl_qq_1 — 40×40
  • figureurl_qq_2 — 100×100

很多示例代码拿到第一个能用的 URL 就存了,结果存的是 30×30。显示在 96px 的位置上,放大三倍。

正确做法是优先取大图;如果拿得到 QQ 号,直接用官方的高清接口:

https://q1.qlogo.cn/g?b=qq&nk=&s=640

s 参数可以给到 640,清晰度完全够用。

小结

  • 头像尺寸按 CSS 尺寸 × 4 准备,别按 1 倍算。
  • 有损格式 + 白底,体积能降一个数量级。
  • 拿头像时先看字段名,figureurl 和 figureurl_qq_2 差了十倍像素。
Dried mango
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇