正常情况下,如果想让左侧黄色20px的元素右侧与父元素齐平,父元素100px,我们的算法是这样:

//100px - 20px
transform: translateX(80px);

x轴移动80px即可达到效果,但是如果我们同时使用scale放大,那么80px就不对了。

transform:scale(2) translateX(80px);

放大两倍后,你会发现平移的距离不对了。

为什么?平移的距离明明就是70px啊!

不着急,我们先看看不使用translateX平移,使用margin-left移动到与父元素右侧齐平再放大是什么样的。

transform: scale(2);
margin-left: 80px;

可以看到,动画确实如我们预期那样,移动80px与父元素右侧齐平,然后在沿着中心点放大2倍。

为了更明显的看出动画,我们给动画加上延迟

transition: margin-left .3s, transform .3s .3s;

可以看出,当我们放大两倍后,黄色子元素变大了,原来的80px位移并不能让他与父元素右侧齐平,我们要换个算法得到正确的位移距离。

transform在没有设置中心点时,默认就是中心点放大

我们如果想齐平,超出部分是需要计算得到,然后(放大后的宽-超出部分的宽)得到子元素显示在父元素内的宽度,然后父元素的宽 - 显示的宽 得到黄色子元素与父元素右侧齐平需要移动的距离

已知我们的子元素宽是20px;他的中心点距离父元素左边的距离是:20/2=10;

因为我们放大了两倍,10*2=20px;沿着中心点放大的左侧宽度是20px;

减去中心点10,也就是20-10=10;我们得到超出的部分是10px;

得到超出部分为10px

那么在父元素内还显示的宽:20*2-10 = 30px;

那么平移的距离:100 - 30 = 70px;

我们测试一下70px是否正确,使用margin-left平移

transform: scale(2);
margin-left: 70px;

可以看到,完美契合。

那么我们实际平移距离是:70px

下面我们来判断一下translateX与scale的关系。

为了方便判断,我们做一条对比元素,元素的宽是140px;在右侧有一个10px宽的的红色背景色。

然后我们设置黄色子元素位移:

transform: scale(2) translateX(70px);

仔细品读一下,可以发现,translateX实际上被放大了两倍,与scale呈倍数关系,放大两倍的黄色元素本身就超出了10px,上面算出来的。

但是translateX并不是以超出去的那条左侧边为位移起点,而是元素scale放大前的左侧为起点进行移动,也就是元素的初始状态的左侧为起点。

所以,元素实际是上是移动了140px,只是因为放大了,左侧超出了10px,所以看上去黄色元素没有移动到140px的参考元素那么宽的距离。

换个人性化的思路,放大和位移是同时的,那我肯定不能用放大后的位置作为位移的基准点。大家都要跑,如果不以起跑线为基准,以跑步对手为基准,那距离不是永远算不准了。

回归正题,那么如果我们想正确的放大和位移,与父元素右侧齐平,那么就应该这样计算:

已知放大后,我们需要平移的距离是:70px

放大的倍率是:2

平移与放大呈倍数关系,如果这么设置:

transform: scale(2) translateX(70px);

元素实际移动了:70*2=140px

所以,正确应该是:

70/2=35px

transform: scale(2) translateX(35px);

看下实际效果

完美达到效果

理解完毕,多脑补

注意

如果scale与translateX位置发生变化,先translateX再进行scale放大,那么translateX就不会被scale放大。

原因我猜测是因为x、y轴的移动是很快的,所以会优先处理,再处理其他的,或者是scale因为要依赖中心点来往周围变形,如果xy轴不先移动完成,放大的中心点会不断变化,所以会等待移动完成处理。

而先scale放大后translateX位移,scale先处理,就会根据根据初始位置的中心点放大,然后放大会影响整个元素,所以位移也跟着受影响。

分类: CSS 标签: scaletaranslate

评论

暂无评论数据

暂无评论数据

目录