对于图片的放大缩小,我们都会自然而然的认为:图片放大,会变得模糊,图片变小会变得较为清晰。放大,会把瑕疵更明显的暴露出来;缩小,可以让瑕疵难以发觉。这是生活中的自然现象。但是,这个现象放到网页上的图片就“变了味”。
变成什么“味”了呢?
通过CSS样式对图片做等比例的放大缩小操作,图片都会变模糊,和通过滚轮对图片做放大缩小操作差异很大。
假设有这样一张图:
通过win11的“图片”软件对其放大缩小。
通过编写HTML将三者在浏览器中显示。
<div style="text-align: center">
<img src="/image_600px.png" />
<img src="/image.png" />
<img src="/image_300px.png" />
</div>
结果如下:
接下来,通过CSS样式调整中间原图的大小。
可以看到,无论是放大还是缩小,中间的原图都变模糊了。从这里我们可以推断出,在浏览器通过CSS的样式对图片做放大缩小操作是不同于专门的图片处理软件的。其效果远不如专门的图片软件处理结果好。
但是在网页上使用图片时是无法避免CSS样式对图片进行放大缩小的(我们总不能为每个尺寸都设置相应的图片吧!)。对于这个问题,前端可以通过CSS样式属性image-rendering
来优化。
在网页上通过CSS样式对图片进行缩放从而导致图片模糊,究其原因是因为浏览器的缩放算法和图片处理软件的不同导致的差异。所以,要解决这个问题,就需要优化浏览器的缩放算法。CSS属性image-rendering
正是为此而存在的。
CSS 属性 image-rendering
用于设置图像缩放算法。它适用于元素本身,适用于元素其他属性中的图像,也应用于子元素。
举个例子,如果有一张尺寸为 100×100px
的图片,但作者有意将尺寸设置为 200×200px
(或50×50px
),然后,图片便会根据 image-rendering
指定的算法,缩小或放大到新尺寸。此属性对于未缩放的图像没有影响。
截取自——《MDN——image-rendering》
image-rendering
可选属性值如下表:
属性值 | 说明 |
---|
auto | 自 Gecko 1.9 (Firefox 3.0)起,Gecko 使用双线性(bilinear)算法进行重新采样(高质量)。 |
crisp-edges | 必须使用可有效保留对比度和图像中的边缘的算法来对图像进行缩放,并且,该算法既不会平滑颜色,又不会在处理过程中为图像引入模糊。合适的算法包括最近邻居(nearest-neighbor)算法和其他非平滑缩放算法,比如 2×SaI 和 hqx-* 系列算法。此属性值适用于像素艺术作品,例如一些网页游戏中的图像。 |
pixelated | 放大图像时, 使用最近邻居算法,因此,图像看着像是由大块像素组成的。缩小图像时,算法与 auto 相同。 |
auto
是浏览器默认的缩放算法;放大图像时,crisp-edges
的效果和auto
一致,缩小时,crisp-edges
的效果比auto
更好;如果设置了pixelated
,无论放大还是缩小图像,看起来都比auto
更明亮了,只不过锯齿也高了。
设置crisp-edges
的效果图:
设置 pixelated
的效果图:
crisp-edges
属性说明:
大多数浏览器不再支持image-rendering: crisp-edges;
这种写法了。需要通过非标准写法来实现设置,兼容性写法如下:
.crisp-edges {
image-rendering: -moz-crisp-edges;
image-rendering: -o-crisp-edges;
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
-ms-interpolation-mode: nearest-neighbor;
image-rendering
兼容性问题:
和其他CSS属性一样,image-rendering
存在浏览器兼容性问题。例如 IE 就没有支持该属性。
有关兼容性的更多资讯,请查看:“image-rendering” | Can I use… Support tables for HTML5, CSS3, etc
尽管借助image-rendering
可以降低浏览器对图像缩放的影响。但是因为浏览器支持问题,这种方式或多或少存在着隐患——不同的浏览器显示效果不一致。因此,为了保证图片的在不同浏览器的保持一致。我们就不能在浏览器上通过CSS对图像做缩放操作。换而言之就是服务器提供不同尺寸的图片。
这要怎么做呢?同样的图片上传不同尺寸到服务器?这是非常吃力不讨好的事情,显然不能成为可行的方案。
正确的做法应该是,服务器存储一张原图,然后根据请求参数的不同导出不同尺寸的图片,再传输给前端。
具体实现过程属于后端范畴,这里就不展开了(我也不会呀!( ̄y▽, ̄)╭ )。
提供一个思路:可使用imgproxy来实现。
相关文档:
以上仅为个人见解,如有不足欢迎指正。
如果您有更好的处理方法,但求指点一二!
对于图片的放大缩小,我们都会自然而然的认为:图片放大,会变得模糊,图片变小会变得较为清晰。放大,会把瑕疵更明显的暴露出来;缩小,可以让瑕疵难以发觉。这是生活中的自然现象。但是,这个现象放到网页上的图片就“变了味”。
最近在做项目的时候发现,在公司电脑上没问题,在自己电脑上确有问题。做的是canvas的项目,在自己电脑上运行的时候,发现,会出现点击选不中的问题还有,canvas刷新会有残影问题。首先可以确定,这两个问题都是canvas元素边界有问题,但是从代码上来看是没问题的,因此我就猜测是否和屏幕有关,毕竟canvas某些问题确实和屏幕有关甚至和硬件显卡有关。
devicePixelRatio属性
果然找出一个属性不同: devicePixelRatio;
然后仔细研究了下这个属性的含义,mdn上解释如下:
此属性返回当前显示设备的物理像素分辨率与CSS像素分辨率的比值。该值也可以被解释为像素大小
网上尝试方案:
1.image-rendering: pixelated; // 像素化,出现锯齿状,pass
2.image-rendering: crisp-edges; // 无效
3.只设置width // 无效,还是会模糊
最终解决方案:
width: 100px;
height: 200px;
object-fit: cover;
关于很多人分不清object-fit各个参数的效果,其实根据单词含义能推测出来:
1.fill:充满
拉伸图片达到设置的宽高(在contain的基础下,哪