最近在做一个视频背景的项目,用到了object-fit
这个 css 属性。但是在万恶的 ie 浏览器上遇到了兼容性问题,ie 不支持该属性,怎么办呢,在万能的 github 上找到了 polyfill 的方法,看完源码把思路记录一下。
首先看一下,object-fit这个属性是干嘛的
使用 object-position 属性来切换"被替换元素"(如video,img,iframe)的内容对象在填充框里展示多少内容。
参数取值
- contain 保留原始宽高比,展示全内容,填充框中剩余内容用空白填充
- cover 保留原始宽高比,不展示全内容,溢出就隐藏
- fill 不保留宽高比,展示全内容,拉伸塞满填充框
- none 不展示全内容,保存原始尺寸,溢出就隐藏。和 cover 的区别在于,cover 的尺寸不一定是原始的
- scale-down 取 cotain 和 none 中尺寸小的一个
浏览器兼容性
只有ie不支持
object-fit-polyfill
github 上还有几个其他的 polyfill,但只有这个支持 video
这里作者针对 object-fit 的各个参数都做了 polyfill,在 src/objectFitPolyfill.js 中
同时提供了最基础版本的 polyfill 文件src/objectFitPolyfill.basic.js,默认支持
object-fit: cover
和object-position: 50% 50%
. 我们就看一下这个源码是怎么实现的:- 上来先判断是否支持objectFit,不支持才需要polyfill。而且判断了是否是edge浏览器,edge16以上只原生实现了img标签的object-fit支持,其他标签还得用polyfill。
1 | // if the page is being rendered on the server, don't continue |
- checkParentContainer 设置父节点样式
- checkParentContainer 设置要polyfill的标签的默认样式
- objectFit 重点来喽
下面以video标签设置polyfill举例分析源码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35var objectFit = function($media) {
// If necessary, make the parent container work with absolutely positioned elements
var $container = $media.parentNode;
checkParentContainer($container);
// Check for any pre-set CSS which could mess up image calculations
checkMediaProperties($media);
// Mathematically figure out which side needs covering, and add CSS positioning & centering
$media.style.position = 'absolute';
$media.style.height = '100%';
$media.style.width = 'auto';
// 参考demo:http://f2estatic.youdao.com/handw/object-fit-polyfill.html
// 1.在设置video标签之前,先设置video标签高度100%,这时候video标签以原始宽高比展示在页面中,未铺满屏幕,只占据左侧。
if ($media.clientWidth > $container.clientWidth) {
// 2.如果video比父节点宽
$media.style.top = '0';
$media.style.marginTop = '0';
// 3.设置左移50%,这样子视频只能看见一半(见下图,红框为可见区域)
$media.style.left = '50%';
// 4.再设置负的margin-left
/* 对于绝对定位元素,负margin会基于其绝对定位坐标再偏移,
唯有的缺点就是你必须知道这个觉得定位元素宽度的和高度才能并设置负margin值使其居中浏览器窗口,
*/
$media.style.marginLeft = $media.clientWidth / -2 + 'px';
} else {
$media.style.width = '100%';
$media.style.height = 'auto';
$media.style.left = '0';
$media.style.marginLeft = '0';
$media.style.top = '50%';
$media.style.marginTop = $media.clientHeight / -2 + 'px';
}
};