如何保持图片清晰度 日常开发中,我们通常会使用一张比较大的图片来作为背景图,或者使用一张比较大的图片来作为图片的缩略图,这样可以保证图片在不同分辨率下都能保持清晰度。
但是这样的问题在于,当分辨率比较小时。根本不需要这么大的图片,浪费带宽并且影响性能。
我们可以让UI同学提供不同分辨率的图片,然后根据屏幕的分辨率来选择不同分辨率的图片来进行展示。这样可以保证图片在不同分辨率下都能保持清晰度,并且不会浪费带宽。
解决方案 我们以 一张 width 500px的图片为例,我们可能会写出如下代码
vue
Image
.img-container {
width: 500px;
margin: a auto;
height: 300px;
background: url('./image/spring@500') no-repeat center center;
}
在浏览器中运行上述代码,我们发现图像并不清晰,元素宽度500px,图片宽度500px,选择一张500宽度的图片有什么问题呢?为什么会模糊呢?
原因:我们没有考虑DPR(设备像素比),当浏览器在缩放时,以以DPR等于2为例,500宽度 的图片会被拉伸到1000px宽度,那自然就不清晰了。我们要保持图片清晰,那我们 background 中的 url的图片宽度就要大于等于元素的宽度乘以DPR。如下
css/* DPR*宽度 */
background: url('./image/spring@[DPR*宽度]') no-repeat center center;我们不可能每次手动修改,我们也不知道用户的DPR是多少,而且DPR也不是一个固定的值,可能是1.5,也可能是2.5,那么怎么办呢? 我们可以使用一个CSS属性 image-set 来解决这个问题。我们可以使用 image-set 来根据DPR来选择不同分辨率的图片。如下
css.img-container {
width: 500px;
margin: a auto;
height: 300px;
background: image-set(
url('./image/spring@1x') 1x,
url('./image/spring@2x') 2x,
url('./image/spring@3x') 3x
) no-repeat center center;
}这样就可以根据DPR来选择不同分辨率的图片了。我们可以使用 1x,2x,3x 来表示不同分辨率的图片。浏览器会根据DPR来选择不同分辨率的图片来进行展示。
在背景中我们可以他通过image-set解决这个问题,但是在img标签中我们就不能使用 image-set 了,我们可以使用 srcset 来解决这个问题。如下
vue
Image
src="./image/spring@1x"
srcset="./image/spring@2x 2x, ./image/spring@3x 3x" />
但是上述方案都存在问题:
image-set 兼容性 有问题,只支持部分浏览器图片应该使用哪一张不仅仅取决于DPR,还取决于img的宽度,img的宽度可能是500px,也可能是1000px,甚至可能是2000px,这样也会导致图片不清晰。所以我们最终需要的图片width 和 DPR 都有关系。
有的时候,因为网页上的一些动画效果改变了图片宽度,尽管DPR没有变化,但图片也应该进行自动切换,遗憾的是img元素不像背景图那样在放大和缩小时候自动切换图片,它只会在初始渲染时选择一张图片。因此,我们只能借助js来解决这些问题。
我们以vue为例 实现一个 ScaleImaege 组件 全部代码参见:https://github.com/pangqiang/vue3-start/blob/main/src/components/ScaleImage.vue