javascript 检测移动设备“缺口”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46318395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Detecting mobile device "notch"
提问by kinggs
With the launch of the iPhone X imminent, I'm trying to get ahead of the game and prepare some of my web applications to handle any design changes - the biggest of which being the new "notch" which houses the front camera.
随着 iPhone X 的发布即将推出,我正在努力领先于游戏并准备我的一些网络应用程序来处理任何设计更改 - 其中最大的是装有前置摄像头的新“缺口”。
I was wondering whether there is, or likely to be, any way of detecting this in Javascript somehow.
我想知道是否有或可能有任何方式以某种方式在 Javascript 中检测到这一点。
Interestingly, Chris Coyier has written an article about The "Notch" and CSSwhich led me to discover the safe-area-inset-rightconstant. Is there any way this can be accessed in Javascript and is this a reliable test.
有趣的是,Chris Coyier 写了一篇关于“Notch”和 CSS的文章,这让我发现了safe-area-inset-right常量。有什么方法可以在 Javascript 中访问它,这是一个可靠的测试。
if (window.constant.safeAreaInsetRight) {
var notch = true;
}
采纳答案by Adriani6
This might be a little hacky however, obtaining the screen available heights and widths and matching them to this specifications would allow us to determine if it is an iPhone X.
然而,这可能有点麻烦,获取屏幕可用的高度和宽度并将它们与此规格匹配将使我们能够确定它是否是 iPhone X。
Please note
请注意
In portrait orientation, the width of the display on iPhone X matches the width of the 4.7" displays of iPhone 6, iPhone 7, and iPhone 8. The display on iPhone X, however, is 145pt taller than a 4.7" display...
在纵向模式下,iPhone X 的显示屏宽度与 iPhone 6、iPhone 7 和 iPhone 8 的 4.7 英寸显示屏的宽度相匹配。然而,iPhone X 上的显示屏比 4.7 英寸显示屏高 145 磅……
So, firstly, you want to check if it is an iPhone via the userAgent, secondly you would check the area of the actual screen (excluding the orientation which defaults to portrait), lastly, once we know that it is an iPhoneX via it's screen dimensions you can determine the orientation (based on the table under the iPhone X diagram above)
因此,首先,您要通过 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
}
}
}
References:
参考:
As for CSS solution, I have found an interesting article about it yesterday which might be of use
至于 CSS 解决方案,我昨天发现了一篇关于它的有趣文章,可能有用
Let's say you have a fixed position header bar, and your CSS for iOS 10 currently looks like this:
假设你有一个固定位置的标题栏,你的 iOS 10 CSS 目前看起来像这样:
header {
position: fixed;
top: 0;
left: 0;
right: 0;
height: 44px;
padding-top: 20px; /* Status bar height */
}
To make that adjust automatically for iPhone X and other iOS 11 devices, you would add a viewport-fit=cover option to your viewport meta tag, and change the CSS to reference the constant:
要为 iPhone X 和其他 iOS 11 设备自动调整,您需要向视口元标记添加 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);
}
It's important to keep the fallback value there for older devices that won't know how to interpret the constant() syntax. You can also use constants in CSS calc() expressions.
对于不知道如何解释 constant() 语法的旧设备,保留回退值很重要。您还可以在 CSS calc() 表达式中使用常量。
回答by Youssef Makboul
// 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;
}
回答by Robert Waddell
Since @youssef-makboul's answer and as commented by @hjellek, iOS has changed from constant() to env() syntax and a fallback is needed to support this approach on all current iPhone X iOS versions.
由于@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;
};
回答by Ben Frain
I hit this recently. You can set the value of a CSS environment variable (env()) to a CSS Custom Property and then read that value in via JavaScript:
我最近打了这个。您可以将 CSS 环境变量 (env()) 的值设置为 CSS 自定义属性,然后通过 JavaScript 读取该值:
CSS:
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:
JS:
getComputedStyle(document.documentElement).getPropertyValue("--sat")
Full info here: https://benfrain.com/how-to-get-the-value-of-phone-notches-environment-variables-env-in-javascript-from-css/
完整信息在这里:https: //benfrain.com/how-to-get-the-value-of-phone-notices-environment-variables-env-in-javascript-from-css/
回答by John Doherty
Add 0.7k notch-detected-eventscript to your page. It fires a notch-detectedevent if the device contains a notch:
将 0.7k检测到的缺口事件脚本添加到您的页面。notch-detected如果设备包含一个缺口,它会触发一个事件:
window.addEventListener('notch-detected', function(e) {
console.log("Notch detected, move shit around");
});
It also add data-notch="true"and data-orientation="portrait|landscape"to the <html>element to allow you to tweak the layout using CSS:
它还向元素添加data-notch="true"和data-orientation="portrait|landscape"以<html>允许您使用 CSS 调整布局:
/* make room for the notch at the top */
html[data-notch][data-orientation="portrait"] body {
padding-top: 44px;
height: calc(100% - 44px);
}
/* make room for the notch at the sides */
html[data-notch][data-orientation="landscape"] body {
padding-left: 44px;
padding-right: 44px;
width: calc(100% - 44px - 44px);
}
Hope this helps!
希望这可以帮助!
回答by Tsavo Knott
Couple of things to add:
补充几点:
Make sure you have the following in your index.html
确保您的 index.html 中有以下内容
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
Additionally:
此外:
Great article on this here: CSS Tricks Notch
这篇很棒的文章:CSS Tricks Notch
回答by Ivan Ferrer
I'm use this:
我在用这个:
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;
};
The CSSis global interface library of typescript:
该CSS是打字稿的全局接口库:
interface CSS {
escape(value: string): string;
supports(property: string, value?: string): boolean;
}
declare var CSS: CSS;
Or in 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 */
}
}


