一种图片标签contain效果的实现方式
这是我在给博客增加“图片点击预览”的时候,碰到的一个小问题,在此记录。
背景
我希望博客内的图片点击时,无论在手机竖屏还是电脑横屏的情况下,都能在屏幕中间特定一个区域 wrap 容器内—“贴边且完整嵌入”,如果用过往一些布局术语讲,应该是叫让图片元素在容器内 “contain 贴边“布局。
所谓图片 contain 贴边是指:
一张图,无论其宽高比例如何,我们都把他完整放到他的父容器中展示(即要把图片全貌展示到容器内部)。 但又有另外一个要求:“贴边”,即放到容器内部的同时,图片较长的那个边要贴到父容器上—也就是说我们希望尽可能让图片在容器内保持尺寸最大来展示。
例如,如下这样竖着的字的一张图:
我期望他在我的父容器内,这样贴边 contain 布局(其中红圈的区域,就是我所谓的 wrap 容器):
而如下这样横着的图片:
我希望他能在我的的父容器内,这样 contain 贴边布局,上下留白:
总体上 html 标签结构如下:
1 | <div class="wrap" style="width: 80%; height: 80%;"> |
background 和 object-fit 无法满足诉求
有同学可能认为目前已经有 background-size: contain,或者 img 标签也可以设置 object-fit: contain
来实现内部内容的 contain 效果。
然而上述 2 个方案均无法让我给图片自身增加 ”描边“ 和 ”阴影效果“, 即上图中图片周围发光效果。因为 background 方案是将图片变成了 div 元素的背景,已经无法再对背景图做其他样式修饰;而 object-fit 则是把 img 标签当成了父容器,也无法再对容器内图片真实的”边“增加描边。
max-width + max-height 不可行
如果通过给 img 标签设置 max-width: 100% 和 max-height: 100% 是否可行呢。
这个确实可以让过大的图片,缩到我的容器内展示,且能变成 contain 效果。然而如果是一个非常小的图,例如 20px * 30px 的图,我的期望是他至少有一条边也要贴到容器的边上—–也就是说此时图片需要放大并贴边展示。
基于“贴边” 且需要给 img 图片自身加阴影的诉求,我暂时没有找到良好而简洁的方案。于是转而采用 js 实现。
js 实现
思路:
- 先将图片的原始尺寸的一条边拉伸到容器该方向的贴边大小。
- 图片等比例拉伸后,检查图片另外一条边长度是否超出容器边界,若超出了则采用超出的这条边的容器尺寸进行图片缩放;若没超出,则采用图片的第一条边进行贴边缩放。
1 | const wrapEle = document.querySelector(".wrap"); |
效果
实际项目中,我的 wrap div 并不需要展示出来(只是计算时候有那么个容器的概念而已),最终实现的效果是让图片预览时能在浏览器中央一块区域“贴边 contain 展示”。
效果如下:
横向图: