H5页面 怎么判断当前iphone设备的具体型号,想区分是否是带灵动岛14pro及以上的机型?

H5页面 怎么判断当前iphone设备的具体型号,想区分是否是带灵动岛14pro及以上的机型?
现在可以判断出是否是iphone 设备,但无法判断是否是14pro 以上的机型?想区分是否是带灵动岛14pro及以上的机型?应该怎么写?

function isiPhone() {
    // 检查是否为iOS设备
    const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);

    // 检查是否为iPhone
    const isiPhone = isIOS && /iPhone/i.test(navigator.userAgent);


    return isiPhone;
}
阅读 1.4k
3 个回答

如果是怕被 灵动岛 遮挡的话,可以使用 env() 来获取安全区信息给不同的机型做适配。
👉 移动端安全区域适配方案 - 南玖的前端blog

如果是单独想给灵动岛设备做一些特殊的业务处理,想用 navigator.userAgent 来获取设备信息就不行了,我这边看有灵动岛机型的 user-agent 信息是没看到有可以识别的特殊标识符。用 iOS 版本来判断是不合适的。
社区里面实现都是通过 user-agent 搭配 devicePixelRatio 和 屏幕分辨率来判断不同的 iPhone 机型。当然这样也很麻烦。


看OP的想法应该是想要获取一下当前设备的型号,这个如果说是在自己研发的App中内嵌的 webview,可以让App开发小伙伴帮忙获取一下设备型号,然后插入到 query 信息中或者通过 JS-Bridge 传递下来。

如果不是 webview 那么除了使用分辨率来判断就没有什么好办法了。之前有考虑通过JS获取屏幕安全区域信息来判断,试了一下灵动岛的 iPhone 顶部安全区域的高度为 59px(刘海屏为 47px

<style>
:root {
    --safe-area-inset-top: env(safe-area-inset-top);
    --safe-area-inset-right: env(safe-area-inset-right);
    --safe-area-inset-bottom: env(safe-area-inset-bottom);
    --safe-area-inset-left: env(safe-area-inset-left);
}
</style>
<script>
  const computeSafeAreaInset = () => {
    const res = { top: 0, right: 0, bottom: 0, left: 0 };
    // Get css properties
    return Object.keys(res).reduce((acc, cur) => {
      const style = getComputedStyle(document.documentElement).getPropertyValue(
        `--safe-area-inset-${cur}`
      );
      return { ...acc, [cur]: style };
    }, res);
  };

  console.log('safeAreaInsetInfo', computeSafeAreaInset());
</script>

但是实现了一下发现有问题。在Safari和微信内置浏览器中竖屏查看时,--safe-area-inset-* 所有的信息返回的都是 0px,只有在横屏查看时才会正确获取到部分安全区域信息。


所以最终还是尝试获取屏幕的分辨率来分辨设备类型。
看了一下所有灵动岛的机型,和13代之后非灵动岛的机型分辨率(分辨率相同的是同颜色)
分辨率

基本上是不会有冲突的,所以方法是可行的:

// 是否为iPhone并且有灵动岛
function iPhoneAndDynamicIsland() {
  // 获取 user-agent 判断是否为 iPhone
  const isIphone = /iphone/gi.test(navigator.userAgent);
  if(!isIphone) return false;
  // 获取屏幕分辨率和设备像素比例
  const devicePixelRatio = window.devicePixelRatio;
  const actualWidth = window.screen.width * devicePixelRatio;
  const actualHeight = window.screen.height * devicePixelRatio;
  // 灵动岛设备分辨率列表
  const dynamicDeviceList = [
    // 数字版
    [2556, 1179],
    // Plus版
    [2796, 1290],
    // Pro版
    [2622, 1206],
    // Pro Max版
    [2868, 1320]
  ];
  // 判断是否为灵动岛设备
  return dynamicDeviceList.some(([vMax, vMin]) => {
    // 按照设备方向判断分辨率是否匹配
    return actualHeight > actualWidth
            ? actualHeight === vMax && actualWidth === vMin
            : actualHeight === vMin && actualWidth === vMax;
  });
}

我在你原来的基础上重新写了个isIPhone14ProOrAbove方法

function isiPhone() {
    // 检查是否为iOS设备
    const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);

    // 检查是否为iPhone
    const isiPhone = isIOS && /iPhone/i.test(navigator.userAgent);

    return isiPhone;
}

function isIPhone14ProOrAbove() {
    if (!isiPhone()) {
        return false;
    }

    const screenWidth = window.screen.width;
    const screenHeight = window.screen.height;
    const devicePixelRatio = window.devicePixelRatio;

    // 检查是否为灵动岛特征
    const hasDynamicIsland = screenWidth >= 430 && screenHeight >= 932 && devicePixelRatio >= 3;

    return hasDynamicIsland;
}

if (isIPhone14ProOrAbove()) {
    console.log('This is an iPhone 14 Pro or above with Dynamic Island.');
} else {
    console.log('This is not an iPhone 14 Pro or above.');
}

媒体查询:

function hasNotch() {
  const hasSafeAreaInset = CSS.supports('padding-top: env(safe-area-inset-top)');
  if (!hasSafeAreaInset) return false;
  
  const div = document.createElement('div');
  div.style.paddingTop = 'env(safe-area-inset-top)';
  document.body.appendChild(div);
  
  const calculatedPadding = getComputedStyle(div).paddingTop;
  document.body.removeChild(div);
  
  return parseInt(calculatedPadding) > 0;
}
推荐问题
宣传栏