18

随着 iPhone X 的发布迫在眉睫,我正试图抢占先机,并准备一些 Web 应用程序来处理任何设计更改——其中最大的一个是容纳前置摄像头的新“缺口”。

我想知道是否有或可能有任何方法以某种方式在 Javascript 中检测到这一点。

有趣的是,Chris Coyier 写了一篇关于“Notch”和 CSS的文章,这让我发现了这个safe-area-inset-right常数。有什么方法可以在 Javascript 中访问它,这是一个可靠的测试。

if (window.constant.safeAreaInsetRight) {
  var notch = true;
}
4

7 回答 7

10

我最近打了这个。您可以将 CSS 环境变量 (env()) 的值设置为 CSS 自定义属性,然后通过 JavaScript 读取该值:

CSS:

:root {
    --sat: env(safe-area-inset-top);
    --sar: env(safe-area-inset-right);
    --sab: env(safe-area-inset-bottom);
    --sal: env(safe-area-inset-left);
}

JS:

getComputedStyle(document.documentElement).getPropertyValue("--sat")

完整信息在这里: https ://benfrain.com/how-to-get-the-value-of-phone-notches-environment-variables-env-in-javascript-from-css/

于 2019-08-29T11:06:51.790 回答
8

然而,这可能有点棘手,获取屏幕可用的高度和宽度并将它们与此规格匹配将使我们能够确定它是否是 iPhone X。

请注意

在纵向上,iPhone X 的显示屏宽度与 iPhone 6、iPhone 7 和 iPhone 8 的 4.7" 显示屏的宽度相匹配。但是,iPhone X 上的显示屏比 4.7" 显示屏高 145pt...

在此处输入图像描述

因此,首先,您想通过 userAgent 检查它是否是 iPhone,其次您将检查实际屏幕的区域(不包括默认为纵向的方向),最后,一旦我们通过它的屏幕知道它是 iPhoneX您可以确定方向的尺寸(基于上图 iPhone X 下的表格)

if (navigator.userAgent.match(/(iPhone)/)){
  if((screen.availHeight == 812) && (screen.availWidth == 375)){

    if((window.innerHeight == "375") && (window.innerWidth == "812")){
      // iPhone X Landscape

    }else{
      // iPhone X Portrait
    }
  }
}

参考:

avil高度

avilWidth

iPhoneX 规格

至于 CSS 解决方案,我昨天发现了一篇关于它的有趣文章,可能有用

假设您有一个固定位置的标题栏,并且您的 iOS 10 CSS 当前如下所示:

header {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 44px;

    padding-top: 20px; /* Status bar height */
}

要为 iPhone X 和其他 iOS 11 设备自动调整,您需要在 viewport 元标记中添加一个 viewport-fit=cover 选项,并更改 CSS 以引用该常量:

header {
    /* ... */

    /* Status bar height on iOS 10 */
    padding-top: 20px;

    /* Status bar height on iOS 11+ */
    padding-top: constant(safe-area-inset-top);
}

对于不知道如何解释 constant() 语法的旧设备,保留备用值很重要。您还可以在 CSS calc() 表达式中使用常量。

文章

于 2017-09-22T10:14:02.947 回答
7

自从@youssef-makboul 的回答和@hjellek 的评论以来,iOS 已经从 constant() 更改为 env() 语法,并且需要在所有当前 iPhone X iOS 版本上支持这种方法。

const hasNotch = function () {
    var proceed = false;
    var div = document.createElement('div');
    if (CSS.supports('padding-bottom: env(safe-area-inset-bottom)')) {
        div.style.paddingBottom = 'env(safe-area-inset-bottom)';
        proceed = true;
    } else if (CSS.supports('padding-bottom: constant(safe-area-inset-bottom)')) {
        div.style.paddingBottom = 'constant(safe-area-inset-bottom)';
        proceed = true;
    }
    if (proceed) {
        document.body.appendChild(div);
        let calculatedPadding = parseInt(window.getComputedStyle(div).paddingBottom);
        document.body.removeChild(div);
        if (calculatedPadding > 0) {
            return true;
        }
    }
    return false;
};
于 2018-02-01T22:32:54.870 回答
6
// iphone X detection

function hasNotch() {
    if (CSS.supports('padding-bottom: env(safe-area-inset-bottom)')) {
      let div = document.createElement('div');
      div.style.paddingBottom = 'env(safe-area-inset-bottom)';
      document.body.appendChild(div);
      let calculatedPadding = parseInt(window.getComputedStyle(div).paddingBottom, 10);
      document.body.removeChild(div);
      if (calculatedPadding > 0) {
        return true;
      }
    }
    return false;
  }
于 2017-10-20T14:22:02.987 回答
2

添加notch-detected-event (0.7k纯JS)

如果检测到缺口,它会将HTML5 数据属性添加到 HTML 元素:

<html data-notch="true" data-orientation="portrait">

允许您使用 CSS 调整布局:

/* make room for the notch at the top */
html[data-notch="true"][data-orientation="portrait"] body {
  padding-top: 44px;
  height: calc(100% - 44px);
}

/* make room for the notch at the sides */
html[data-notch="true"][data-orientation="landscape"] body {
  padding-left: 44px;
  padding-right: 44px;
  width: calc(100% - 44px - 44px);
}

或者监听notch-detected事件并执行一些 JS:

window.addEventListener('notch-detected', function(e) {
  console.log("Notch detected, move shit around");
});
于 2019-12-05T23:28:16.337 回答
0

有几点要补充:

确保您的 index.html 中有以下内容

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

此外:

很棒的文章在这里:CSS Tricks Notch

于 2019-02-13T04:03:42.600 回答
0

我用这个:

function hasNotch() {

    //iphone X 1.11
    if (document.documentElement.clientHeight == 812 && document.documentElement.clientHeight == 375 && !!window.matchMedia && window.matchMedia("only screen and (-webkit-device-pixel-ratio: 3)").matches && iOSversion()[0] == 11) {
        return true;
    }

    var proceed = false;
    var div = document.createElement('div');
    if (CSS.supports('padding-bottom: env(safe-area-inset-bottom)')) {

        div.style.paddingBottom = 'env(safe-area-inset-bottom)';
        proceed = true;
    } else if (CSS.supports('padding-bottom: constant(safe-area-inset-bottom)')) {

        div.style.paddingBottom = 'constant(safe-area-inset-bottom)';
        proceed = true;
    }
    if (proceed) {
        return true;
    }

    return false;
};

CSS是 typescript 的全局接口库:

interface CSS {
    escape(value: string): string;
    supports(property: string, value?: string): boolean;
}
declare var CSS: CSS;

或在CSS中:

$margin_max_constant_notch:unquote('max(-12px, constant(safe-area-inset-left))');
$margin_max_env_notch:unquote('max(-12px, env(safe-area-inset-left))');

/*** iphone X 1.11, iphone XS (quote is OR) ***/
@media only screen
and (device-width : 375px)
and (max-device-width : 812px)
and (-webkit-device-pixel-ratio : 3),
 /*** iphone XR ***/
screen and (device-width : 414px)
and (device-height : 896px)
and (-webkit-device-pixel-ratio : 2),
  /*** iphone XS Max ***/
screen and (device-width : 414px)
and (device-height : 896px)
and (-webkit-device-pixel-ratio : 3),
  /*** iphone XS Max Retina ***/
only screen and (-webkit-min-device-pixel-ratio: 3),
only screen and (   min--moz-device-pixel-ratio: 3),
only screen and (     -o-min-device-pixel-ratio: 3/1),
only screen and (        min-device-pixel-ratio: 3),
only screen and (                min-resolution: 458dpi),
only screen and (                min-resolution: 3dppx),
/** Google Pixel 3 XL  **/
screen and (device-width: 360px)
and (device-height: 740px)
and (-webkit-min-device-pixel-ratio: 4),
only screen and (   min--moz-device-pixel-ratio: 4),
only screen and (     -o-min-device-pixel-ratio: 4/1),
only screen and (        min-device-pixel-ratio: 4),
only screen and (                min-resolution: 523dpi),
only screen and (                min-resolution: 4dppx) {

    @media(orientation: portrait) {

       /* mobile - vertical */


        @media (max-width: 768px) {
         /* up to 768px */
        }

        @media (max-width: 480px) {
         /* up to 480px */
        }

       @media only screen and (max-width: 400px) {
           /* up to 400px */
        }


    }
    @media(orientation: landscape) {
        html,body {
            padding: $margin_max_constant_notch;
            padding: $margin_max_env_notch;
        }

        /* mobile - horizontal */

        @media screen and (max-width: 900px) {

          /* up to 900px */
        }

    }
}

/** iphone X 1.12 **/
@supports(padding: max(0px)) {
@media screen and (device-width : 375px)
and (device-height : 812px)
and (-webkit-device-pixel-ratio : 3) {
    @media(orientation: portrait) {

       /* mobile - vertical */

        @media (max-width: 768px) {
           //até 768px
        }

        @media (max-width: 480px) {
         /* up to 480px */
        }

        @media only screen and (max-width: 400px) {
        /* up to 400px */
        }

      }
      @media(orientation: landscape) {
        html, body {
          padding: $margin_max_constant_notch;
          padding: $margin_max_env_notch;
        }

        @media screen and (max-width: 900px) {
         /* up to 900px */
        }
      }
   }
}

/** iphone 8 **/
@media only screen
and (device-width : 375px)
and (device-height : 667px)
and (-webkit-device-pixel-ratio : 2),
  /** iphone 8 PLUS **/
screen  and (device-width : 414px)
and (device-height : 736px)
and (-webkit-device-pixel-ratio : 3) {
  @media(orientation: portrait) {

  /* mobile - vertical */

  }
  @media(orientation: landscape) {

  /* mobile - horizontal */
  }
}

@media only screen
  /** IPADS **/
and (min-device-width: 1024px)
and (max-device-width: 1366px)
and (-webkit-min-device-pixel-ratio: 2) {

 /* for ipads */

  @media(orientation: portrait) {

  /* ipad - vertical */

  }
  @media(orientation: landscape) {

  /* ipad - horizontal */
  }

}
于 2019-07-23T11:05:01.460 回答