写在前面

最近在做一个东西,有这么一个需求,希望在平板下的横屏时,改变一个盒子的padding。
看起来很简单,那就动手干

  1. window.addEventListenser('orientationchange', handle);
  2. function handle() {
  3. if(Math.abs(window.orientation) === 90) {
  4. // 加类名等改样式操作,横屏
  5. } else {
  6. // 去掉样式
  7. }
  8. }

碰到麻烦

就上述这么一个简单的逻辑,碰到了两个难题,一个一个来说一下

1.orientationchange 不是 change after 而是ing

希望是在屏幕方向变换后,再去改变样式,但是这个事件是发生时就会触发。那么可能就会有个问题,拿到的window.orientation不是屏幕方向变换后的,而是旧的。怎么解决呢。有两个方案,一个是设置个定时器,而是设置个延时器。我这里采用第二种。

  1. function handle() {
  2. // 假设用户不会频繁切换横竖屏,如果有 设置一个timer 然后依据情况clearTimer
  3. setTimeout(function(){
  4. if(Math.abs(window.orientation) === 90) {
  5. // 加类名等改样式操作,横屏
  6. } else {
  7. // 去掉样式
  8. }
  9. },0); // 利用事件队列机制,放到宏任务队列中
  10. }

2.一般情况下orientation 可以通过0,180,90,-90等判断横竖屏,但总有例外

现在的pad都支持分屏,横屏pad,分屏后,就变成了两个“竖屏”(场景A),但是orientation还是0或者180。同理,pad竖屏状态下,分屏后,就变成了两个“横屏”(场景B),但是orientation还是90或-90。懵逼了。这怎么玩。
给一下问题分析的过程
1.场景A,虽然js里面log的window.orientation是“横屏”,但是生效的样式(写了@media screen and (orientation:portrait))是竖屏的。那证明css层面展示的屏幕是对的。
2.搜索一下media这个东西有没有什么相关的jsapi可以用,找到了matchMedia这个api
matchMedia(mediaQueryString); 返回一个对象,我们用到的是matchMedia(``_mediaQueryString_``).matches表示的是是否匹配:就好比,我们css里面写的媒体查询一样,这例就是这个mediaQueryString生效的结果Boolean值
那么代码就可以改造一下了
_

  1. var mediaQueryLandscape = window.matchMeida('(orientation:landscape)');
  2. function handle() {
  3. // 假设用户不会频繁切换横竖屏,如果有 设置一个timer 然后依据情况clearTimer
  4. setTimeout(function(){
  5. if(mediaQueryLandscape.matches) {
  6. // 加类名等改样式操作,横屏
  7. } else {
  8. // 去掉样式
  9. }
  10. },0); // 利用事件队列机制,放到宏任务队列中
  11. }

两个问题完美解决

小结一下

1.orientation其实准确来说不能算是“横竖屏”的判断依据,要看设备设计的理念了,有个pad,默认形态是竖着,有的则是横着。
2.我们web里面提到的横竖屏,其实跟设备形态无关,至于视口的宽高有关,竖屏:宽<高,横屏:高<=宽,其实真的有正方形的设备,不管怎么旋转都是横屏。
3.要准确的判断横竖屏,要么通过宽高,要么通过matchMedia(移动端推荐使用,PC旧浏览器不兼容)