o2team / H5Skills

移动端开发技巧集合
831 stars 80 forks source link

前端观测:正确理解rotate3d #46

Open leeenx opened 7 years ago

leeenx commented 7 years ago

最近,收到反馈说3D翻转在小米4下展示异常。秉承实事求是的精神,拿了部安卓机子做观测。

观测的机型:华为荣耀3C(没有小米4,华为荣耀3C与米4的异常一致)

异常截图如下:

图一

rotate3d的具体调用如下:

transform: rotate3d(0,0,0,90deg);

修改为:

transform: rotate3d(1,0,0,0deg);

问题得以解决:

图二

rotate3d(0,0,0,90deg) 与 rotate3d(1,0,0,90deg) 有什么实质的区别。w3c 相关解释:

specifies a 3D rotation by the angle specified in last parameter about the [x,y,z] direction vector described by the first three parameters. A direction vector that cannot be normalized, such as [0,0,0], will cause the rotation to not be applied.

来源:https://www.w3.org/TR/css-transforms-1/;

根据w3c的说法应该是 rotate3d(0,0,0,90deg) 会不生效。而出问题的安卓机型却把 rotate3d(0,0,0,90deg) 降级为 rotate(90deg) 或 rotateZ(90deg)了。

w3c对rotate3d的用法如下:rotate3d( <number> , <number> , <number> , <angle>)

第一次观测

为了便于说明,把上式写成 rotate3d(x,y,z,degree);

本人一开始对这个的理解是,x,y,z轴方法的旋转角度为 x * degree, y * degree ,z * degree。而下面的观测结果,打了我一巴掌,以下几个rotate3d的效果是一样的:

  1. transform: rotate3d(-1,0,0,60deg);
  2. transform: rotate3d(1,0,0,60deg);
  3. transform: rotate3d(0.1,0,0,60deg);

观测结果如下:

mac,adnroid和ios的表现都一样,只截mac上的chrome浏览的显示结果

这次观测的结论是: x,y,z的取值是:x?degree:0,y?degree:0,z?degree:0

如果这个观测结论是正确的话,很容易推断得出,一个立方体只能沿七条线进行3D翻转:

第二次观测

使用以下代码验证第一次观测的结论是否正确:

<style>
.rect{
  position: absolute;
  width: 100px;
  height: 100px;
  background-color: #333;
  left: 100px;
  top: 100px;
  -webkit-transform: rotate3d(1,1,0,30deg);/*观测关键代码*/
}
</style>
<div class="rect"></div>

观察结果如下:

图3

将rotate3d更改为:

-webkit-transform: rotate3d(1,.5,0,30deg);

按上次观测结论,这次观测与上次观测结果应该完全相同。而观测结果却不是,如下:

图4

第二次观测的结论为:x,y,z轴方法的旋转角度为 x * degree, y * degree, z * degree。(与本人最开始的理解一致)

第三次观测

第一次和第二次观测结果完全不同,但是又各有事实做证,于是我猜测:

1. rotate3d的x,y,z轴的角度值的计算为:x * degree,y * degree,z * degree; 2. 当且仅当x,y,z三个值中有两个值为0时,剩余的非0值取1;

沿用第二次观测的代码,观察下面几种情况:

  1. -webkit-transform: rotate3d(1,1,0,30deg);
  2. -webkit-transform: rotate3d(1,.4,0,30deg);
  3. -webkit-transform: rotate3d(1,1,1,30deg);
  4. -webkit-transform: rotate3d(1,4,2,30deg);

观测结果如下:

与猜测结果一致。

结论

rotate3d对x,y,z三个轴的取值遵守以下两点:

1. rotate3d的x,y,z轴的角度值的计算为:x * degree,y * degree,z * degree;

2. 当且仅当x,y,z三个值中有两个值为0时,剩余的非0值取1;

基于以上两点,rotate3d 的正确用法是:

1. 单轴翻转使用rotateX,rotateY,rotateZ
2. 使用rotate3d要避免 rotate3d(0,0,0,deg) 的情况

直接放弃rotate3d转用 rotateX,rotateY,rotateZ可以简单直接地避开所有风险点。