zoom和transform:scale()的区别

时间:2022-05-07 14:49:38

zoom和transform:scale()都可以用于缩放,目前移动端存在各种各样不同屏幕大小的手机,为了兼容不同宽度的屏幕,我们可以基于某一屏幕宽度大小(比如iPhone5的320,这个根据设计稿来)做出页面后,再对页面进行缩放以兼容其他屏幕宽度。

定义

zoom和transform:scale()具体有什么区别呢?先来看看官方的定义:

Specifies the initial zoom factor for the window or viewing area. This is a magnifying glass type of zoom. Interactively changing the zoom factor from the initial zoom factor does not affect the size of the initial or the actual viewport.

zoom相当于是一个放大镜,缩放被zoom的元素不会影响初始或实际视口的大小。

zoom的取值可以为数值和百分比值,不能取负值。

A transformation is applied to the coordinate system an element renders in through the transform property. This property contains a list of transform functions. The final transformation value for a coordinate system is obtained by converting each function in the list to its corresponding matrix like defined in Mathematical Description of Transform Functions, then multiplying the matrices.

先来看看transform的定义,transform的值是基于坐标系统的,transform的变换过程实际上是矩阵变换的过程,被transform的元素要经过一系列的矩阵运算最终确定其坐标。

The value of the transform property is a list of transform-function...specifies a 2D scale operation by the [sx,sy] scaling vector described by the 2 parameters. If the second parameter is not provided, it takes a value equal to the first.

scale()是transform的一个属性值,这是一个缩放函数。当一个元素被定义了transform:scale(x,y),可以控制其x方向和y方向上的缩放比例,如果只有一个参数,那么第二个参数与第一个参数相等。

scale的取值只能是数值,但是可以为负数。

实际应用

先来看一个简单的demo

兼容问题

从demo中可以看出zoom缩放是相对于左上角的,而scale默认是相对于元素的中心点缩放的,scale可以通过设置transform-origin来改变缩放的相对位置,当设置transform-origin: 0 0时,scale缩放可以达到和zoom缩放相似的结果。

前面提到缩放可以应用于移动端各种不同宽度的屏幕的适配上,那么我们就来看看zoom缩放和scale缩放在屏幕适配上的具体差异。下图从左到右分别是:无缩放在iPhone5上的表现,zoom:1.17在iPhone6上的表现,transform:scale(1.17)在iPhone6上的表现。

zoom和transform:scale()的区别

代码如下:

HTML

<div class="container">
<div class="box red"></div>
<div class="box blue"></div>
<div class="box red"></div>
</div>

CSS

html,body {height: 100%;}
.container {height: 100%;}
.box {height: 160px; font-size: 20px; text-align: center;}
.red {background-color: rgba(255,0,0,.5);}
.blue {background-color: rgba(0,0,255,.5);}

外层容器宽高为100%,占满整个屏幕。因为zoom是作用在body下面的这个占满了整个屏幕的容器上,根据定义我们可以说在这里使用zoom其实是缩放了整个屏幕(也就是视口),其实就跟在浏览器中放大页面的效果一样:

zoom和transform:scale()的区别

那么scale为什么会出现滚动条呢?根据transform的定义,transform的变换过程是基于坐标系统的,也就是说,外层容器在缩放前四个角的坐标分别为(0,0),(100%,0),(0,100%),(100%,100%),经过以(0,0)为变换中心的scale之后,四个角的坐标变为(0,0),(117%,0),(117%,0),(117%,117%),超出了视口本身的大小,所以出现了滚动条。

这么看起来,好像兼容的时候就应该用zoom了呢!一开始我也是这么想的,但是后来经过同事的指点,scale的问题也是有解决办法的:那就是给外层容器,即要缩放的那个元素,设置固定的宽高。注意,不是百分比,而是要设置绝对值!比如,设计稿是按照iPhone5的屏幕大小来做的,那么就给外层容器设置width: 320px; height: 504px;,这样设置之后再用scale就不会出现滚动条了。当然,用zoom也是一样的效果。

渲染

从上面的demo中还可以看出被缩放的元素的宽高用js获取时还是缩放前的原始宽高,但是,在审查元素时zoom和scale还是有区别的:

zoom和transform:scale()的区别

zoom还有一点比较诡异,戳demo,当元素的宽度不显式设置(即默认100%)或者设置为百分比,用zoom对元素缩小之后宽度竟然比原来大了!大了!了!如果是放大的话宽度就会比原来小!小!

所以,如果你要获取元素缩放之后的宽高,用zoom似乎是比较麻烦的。scale的话就比较简单了,只要把用js获取到的宽高*缩放的倍数就是元素缩放之后的实际宽高了。

另外,zoom对性能不友好,会影响到页面中的其他元素,在文档流中给任一元素加上zoom会引起整个页面的重新渲染。从最开始的demo中就可以看到被zoom的元素的父元素的高度明显小了。而scale只是在当前元素上重绘,不会影响其他元素。

其他

如果被缩放的元素是宽高是以rem为单位,那么zoom作用在该元素上无效,除了文字或者不是以rem为单位的子元素,而scale表现则正常。demo看这里

所以,到底是用zoom还是scale,还是要具体情况具体分析。

第一次写文章,才疏学浅,如有错漏,欢迎斧正。