在HTML5中检测iPad Mini
苹果公司的iPad Mini是iPad 2的一个更小的克隆,它比我们想要的更多。 在JavaScript中, window.navigator
对象公开了Mini和iPad 2的相同值。到目前为止我的testing来检测差异并没有成功。
为什么这很重要?
由于iPad Mini和iPad 2屏幕像素相同,实际尺寸(英寸/厘米)不同,因此它们的PPI (像素每英寸)也不相同。
对于networking应用程序和游戏提供友好的用户界面,某些元素的尺寸相对于用户的拇指或手指位置进行了调整,因此,我们可能想要缩放某些图像或button以提供更好的用户体验。
我到目前为止尝试过的东西(包括一些非常明显的方法):
-
window.devicepixelratio
- 以cm为单位的CSS元素宽度
- CSS媒体查询(例如
resolution
和-webkit-device-pixel-ratio
) - 类似单位的SVG图纸
- 做各种CSS webkit转换一段时间,并使用
requestAnimFrame
计算渲染帧(我希望能够检测到一个可测量的差异)
我是新鲜的想法。 你呢?
更新感谢迄今的回应。 我想评论一下投票反对检测iPad mini与2苹果有呃,一个指导方针来统治他们。 好吧,这是我的推理,为什么我觉得在世界上真正知道一个人是否使用iPad mini或者2.使用我的推理你喜欢什么。
iPad mini不仅是一个小得多的设备(9.7英寸与7.9英寸),而且其外形允许不同的用途。 除非你是查克·诺里斯(Chuck Norris),否则在游戏中通常会用两只手握住iPad 2。 迷你比较小,但是它也轻很多,可以让玩家一手拿着游戏,用另一种方式轻扫或轻敲。 作为一名游戏devise师和开发者,我只想知道它是否是一个迷你游戏,所以我可以select为玩家提供不同的控制策略(例如,在一组玩家进行A / Btesting之后)。
为什么? 那么,大多数用户倾向于使用默认设置,所以在玩家加载游戏的时候,不要在屏幕上放置一个虚拟的游戏杆,并在屏幕上放置一些其他的基于点击的控件(这里只给出一个任意的例子)游戏的第一次是我和其他游戏devise师可能会喜欢的。
所以恕我直言,这超出了厚厚的手指/指导方针的讨论,只是苹果和所有其他供应商应该做的事情:让我们唯一识别您的设备, 思考不同,而不是遵循指导方针。
播放立体声audio文件,并在右声道和左声道的音量较高时比较加速度计响应 – iPad2具有单声道扬声器,而iPad Mini则具有内置立体声扬声器。
需要您的帮助来收集数据,请访问此页面,并帮助我收集这个疯狂的想法的数据。 我没有iPad mini,所以我真的需要你的帮助
更新: 它们看起来像这些值是在创build标签时报告视口的宽度和高度,并且它们在旋转时不会改变,所以这个方法不能用于设备检测 !
您可以使用screen.availWidth
或screen.availHeight
因为它们看起来与iPad Mini和iPad 2不同。
小型平板电脑
screen.availWidth = 768 screen.availHeight = 1004
iPad 2
screen.availWidth = 748 screen.availHeight = 1024
资料来源: http : //konstruktors.com/blog/web-design/4396-detect-ipad-mini-javascript/
我知道这可能是一个低科技的解决scheme,但由于我们似乎还没有拿出任何东西呢..
我假设你已经检查了大多数其他设备,所以我看到以下情况可能。
你可以检查所有可能的最stream行的设备,需要特殊的CSS /大小,如果匹配没有任何一个假设它是一个iPad的迷你或只是问用户?
// Device checks here ... else { // it would probably be better to make this a nicer popup-thing var mini = prompt("Are you using a iPad mini? Press yes for a better user experience"); // Store the result for future visits somehow. }
我知道现在看起来似乎是一个愚蠢的做法,但是如果我们目前还没有办法确定设备是iPad mini还是iPad 2,那么至less该网站将可用于iPad mini设备。
你甚至可以这样做:
“为了给您提供最佳的浏览体验,我们尝试检测您的设备types,以便为您的设备定制网站。不幸的是,由于局限性,这并不总是可能的,目前我们无法确定您是使用iPad 2还是iPad迷你通过使用这些方法。
为了获得最佳浏览体验,请在下面select您正在使用的设备。
这个select将被存储用于将来访问该设备上的网站。
[] iPad 2 [*] iPad mini [] Ancient blackberry device
“
我不完全熟悉你可以做什么,不能在Javascript中做客户端。 我知道你可以得到一个用户的IP,但是有可能得到一个用户的MAC地址? iPad2和iPad mini之间的距离是不一样的?
我知道这是一个可怕的解决scheme,但目前区分iPad Mini和iPad 2的唯一方法是检查其内部版本号并将每个内部版本号映射到相关设备。
我举个例子:iPad mini 6.0版本正在曝光“ 10A406
”作为内部版本号,而iPad 2则曝光了“ 10A5376e
”。
这个值可以通过用户代理( window.navigator.userAgent
)上的正则expression式轻松获得; 该号码前缀为“ Mobile/
”。
不幸的是,这是检测iPad Mini的唯一明确方法。 我build议采用一个viewport
相关的方法(在支持的情况下,使用vh / vw单位)来正确显示不同屏幕尺寸的内容。
tl; dr不要弥补iPad mini和iPad 2之间的差异,除非你还会在脂肪和手指之间进行补偿。
苹果似乎故意不让你说出区别。 苹果似乎不希望我们为不同大小版本的iPad编写不同的代码。 我自己并不是苹果公司的一员,我不知道这是肯定的,我只是说这就是它的样子。 也许,如果开发者社区想出了一个迷你iPad迷你探测器,苹果可能会故意在未来的iOS版本中打破这个探测器。 苹果希望你将你的最小目标大小设置为44个iOS点,而iOS将以两种尺寸显示,比如较大的iPad尺寸和较小的iPhone / iPad迷你尺寸。 44分足够大了,你的用户一定知道他们是否在小iPad上,这样可以自己赔偿。
我build议回到你要求检测器的陈述理由:为最终用户的舒适度调整目标尺寸。 通过决定在大型iPad上devise一种尺寸,在小型iPad上devise另一种尺寸,你就可以决定所有的人都有相同的尺寸。 如果您的devise足够紧密,以至于iPad 2和iPad mini的尺寸差异会有所不同,那么与我和我妻子之间的手指尺寸将会产生更大的差异。 所以补偿用户手指的大小,而不是iPad模式。
我有一个关于如何测量手指大小的build议。 我是一个本地的iOS开发人员,所以我不知道这是否可以在HTML5中完成,但这里是我将如何在本机应用程序中测量手指大小。 我会让用户捏住两个物体,然后测量他们靠得多近。 较小的手指会使物体靠得更近,您可以使用此测量值来导出比例因子。 这会自动调整为iPad的大小。 同一个人在iPad mini上的屏幕点数将大于在iPad 2上的屏幕点数。对于游戏,您可以将其称为校准步骤,或者甚至不称呼它。 把它作为一个起点。 例如,在射击游戏中,玩家将弹药放在枪中,并进行一系列的动作。
不幸的是,目前看起来这是不可能的: http : //www.mobilexweb.com/blog/ipad-mini-detection-for-html5-user-agent
前两天,我啾啾了第一个检测到的问题:“ 确认iPad Mini User Agent与iPad 2相同 ”。 我收到了数百个答案,说用户代理嗅探是一个不好的做法,我们应该检测function而不是设备等等。
那么,是的,你是对的,但它与问题没有直接关系。 而且我还需要补充第二个坏消息: 没有客户端的技术来做“特征检测” 。
要求用户把他们的iPad从地面上几千英尺落下。 然后使用内部加速计来测量iPad达到terminal速度的时间。 较大的iPad具有更大的阻力系数,并且应该在比iPad Mini更短的时间内达到terminal速度。
以下是一些示例代码,以帮助您入门。
function isIPadMini( var timeToReachTerminalVelocity ) { return (timeToReachTerminalVelocity > IPAD_MINI_THRESHOLD); }
当苹果不可避免地以不同的forms发布下一代iPad时,您几乎肯定需要重新审视这些代码。 但我相信你会保持在最新的东西,并保持这个黑客每个新版本的iPad。
这是一个狂野的拍摄,但iPad 2和iPad mini之间的区别之一是前者没有三轴陀螺仪。 也许可以使用WebKit设备定位API来查看可以从中获得哪些信息。
例如, 这个页面似乎表明,如果设备有一个陀螺仪,你只能得到rotationRate
值。
对不起,我不能给一个工作的POC – 我没有访问一个iPad的迷你。 也许有人对这些方向API有更多的了解,可以在这里发出邀请。
那么,iPad 2和iPad Mini有不同大小的电池。
如果iOS 6支持,您可以使用window.navigator.webkitBattery.level
从0.0..1.0
获取当前的电池电量。 在硬件或软件的某个级别,可能计算为CurrentLevel / TotalLevel
,其中都是整数。 如果是这样,那么将会产生1 / TotalLevel
倍数的1 / TotalLevel
。 如果你从这两个设备中获取大量的电池电量读数,并计算出battery.level * n
那么你可以find一个n的值,所有的结果开始接近整数,这会给你iPad2TotalLevel
和iPadMiniTotalLevel
。
如果这两个数字不同,并互补,则可以在生产中计算battery.level * iPad2TotalLevel
和battery.level * iPadMiniTotalLevel
。 无论哪个更接近整数将指示哪个设备正在使用。
对不起,在这个答案ifs的数量! 希望有更好的东西会出现。
编辑1:我原来的答案,下面,是“不要这样做”。 为了积极:
我认为真正的问题与iPad X和iPad mini没有任何关系。 我认为这是关于优化用户的人机工程学UI元素的尺寸和位置。 您需要确定用户手指的大小,以便驱动您的UI元素大小,或者定位。 这也是,而且应该可能到达,而不需要真正知道你在哪个设备上运行。 让我们夸大:你的应用程序运行在40英寸对angular线屏幕上。 不知道品牌和型号还是DPI。 你如何确定控制的大小?
您需要在网站/游戏中显示一个button,它是门控元素。 我会留给你决定在哪里或如何做到这一点是有道理的。
虽然用户将这看作是一个单一的button,但实际上,它将由一个小巧紧凑的buttonmatrix组成,这些button在视觉上被覆盖以显示为单个button图像。 想象一个100×100像素的button,由400个button组成,每个button5 x 5像素。 你需要试验一下,看看这里有什么意义,你的抽样需要多less。
可能的button数组的CSS:
.sense_row { width:100px; height:5px; margin:0; padding:0; } .sense_button { float:left; width:3px; height:3px; padding:0px; margin:0px; background-color:#FF0; border:1px solid #000; }
结果数组:
当用户触摸buttonarrays时,您将有效地获得用户手指的接触区域的图像。 然后,您可以使用任何您想要的标准(可能是经验派生的),以便获得一组数字,您可以使用这些数字按照您的要求缩放和定位各种UI元素。
这种方法的美妙之处在于你不再关心你可能处理的设备名称或型号。 你所关心的只是用户手指相对于设备的大小。
我会想象这个sense_arraybutton可以作为入口过程的一部分隐藏到应用程序中。 例如,如果它是一个游戏,也许有一个“播放”button或各种button与用户的名字或手段来select他们将播放什么水平,等等。你明白了。 sense_arraybutton可以居住在用户为了进入游戏而必须触摸的任何地方。
编辑2:只是注意到你可能不需要那么多的感觉button。 一组同心圆或button排列成一个巨大的星号*
可能会很好。 你必须试验。
下面我的回答就是,我给你两面硬币。
老解答:
正确的答案是:不要这样做。 这是一个坏主意。
如果你的button太小,以至于它们变得无法使用,你需要增大button的大小。
如果我在原生iOS应用程序中学到了什么,那么试图智取苹果是一个不必要的痛苦和恶化的公式。 如果他们select不让你识别这个设备,那是因为在他们的沙箱里,你不应该这么做。
我想知道,你是在调整人像还是风景的大小?
是的,检查陀螺仪是一个好的方面。 你可以轻松地做到这一点
或类似的东西
window.ondevicemotion = function(event) { if (navigator.platform.indexOf("iPad") != -1 && window.devicePixelRatio == 1) { var version = ""; if (event.acceleration) version = "iPad2"; else version="iPad Mini"; alert(version); } window.ondevicemotion = null;
}
没有任何iPad可以testing。
微型基准testing,计算iPad 2上的X微秒和iPad mini上的Y秒。
这可能不够准确,但可能有一些指示,iPad mini芯片更有效率。
要求所有使用iPad2用户代理的用户使用内置摄像头提供照片,并使用HTML File API检测分辨率。 由于相机的改进,iPad Mini的照片分辨率会更高。
您也可以创build一个不可见的canvas元素,并使用Canvas API将其转换为PNG / JPG格式。 我没有办法testing它,但由于底层的压缩algorithm和设备的像素密度,结果可能会有所不同。
你总是可以问用户?
如果用户看不到button或内容,则给他们一个自己pipe理缩放的方法。 你总是可以build立一些缩放button到网站,使内容(文字/button)变大/变小。 这将是(几乎)保证适用于任何目前的iPad的决议,可能任何未来的决议苹果决定他们想。
这不是你提出的问题的答案,但我希望这会比说“不要那样做”更有用:
为了不检测iPad Mini,为什么不检测用户是否遇到难以控制的问题(或者:一直在控制的一个子区域内击中),并且为了适应他们而增大/减小控制的大小?
无论硬件如何,需要更大控制的用户都可以获得。 用户谁不需要更大的控制,并希望看到更多的内容也得到这一点。 这并不是一件简单的事情,只要检测硬件,就会有一些微妙的事情能够得到正确的结果,但是如果仔细地完成,那可能会非常好。
这让我想起了电影“平衡:
“你会说什么是从牧师教徒那里获得武器最简单的方法?
“你问他。”
我们很习惯于争取解决scheme,有时候,最好问问。 (有很好的理由,我们通常不这样做,但总是一个选项。)这里的所有build议都非常出色,但是一个简单的解决scheme可能是让程序在启动时询问他们使用的是哪个iPad 。
我知道这是一个厚颜无耻的答案,但我希望这是一个提醒,我们不必争取一切。 (我已经支持自己的下注了:P)
一些例子:
- 操作系统安装过程中的键盘检测有时无法检测到特定的键盘,因此安装程序必须询问。
- Windows会询问您连接的networking是家庭networking还是公共networking。
- 计算机无法检测到即将使用它的人,因此他们需要用户名和密码。
Best of luck – I hope you find an awesome solution! If you don't, though, don't forget this one.
Not answering the question, but the question behind the question:
Your goal is to improve the user experience on a smaller screen. The appearance of the UI controls is one part of it. Another part of UX is the way the application responds.
What if you make the area that responds to taps big enough to be user friendly on the iPad Mini while keeping the visual representation of the UI controls small enough to be visually pleasing on the iPad?
If you have gathered enough taps that were not in the visual area, you can decide to visually scale the UI Controls.
As a bonus, this works for big hands on iPad as well.
All solutions here are not future-proof (what prevents Apple from releasing an iPad with the same screen size as the iPad 2 but same resolution as the iPad Mini). So I came up with an idea:
Create a div with 1 inch width and append it to the body. Then I create another div with 100% width and append it to the body:
var div1= $("<div/>").appendTo(document.body).width("1in"); var div2= $("<div/>").appendTo(document.body).width("100%");
jQuery width() function always returns values in pixels so you can just:
var screenSize= div2.width() / div1.width();
screenSize now holds the size available to the application in inches (beware rounding erros though). You can use that to place your GUI the way you like it. Also don't forget to remove the useless divs afterwards.
Also note that the algorithm proposed by Kaspars not only will not work if the user runs the application as full screen, but it will also break if Apple patches the browser UI.
This won't differentiate the devices, but as you explained in your edit what you actually wants to know is the device screen size. My idea will also not tell you exactly the screen size, but it will give you an even more useful information, the actual size (in inches) that you have available to draw your GUI.
EDIT: Use this code to check if it actually works on your device. I don't own any iPads to test it on.
var div1= $("<div/>").appendTo(document.body).width("1in").height("1in").css("position", "absolute"); var div2= $("<div/>").appendTo(document.body).width("100%").height("100%").css("position", "absolute"); var width= div2.width() / div1.width() var height= div2.height() / div1.height() alert(Math.sqrt(width*width + height*height));
It should popup a window with your screensize in inches. It seems to work on my laptop, returning 15.49 while my laptop screen is marketed as 15.4''. Can anyone test this on iPads and post comments please? Don't forget to run it full screen.
EDIT2: It turns out that the page I tested it in had some conflicting CSS . I fixed the test code to work properly now. You need position: absolute on the divs so you can use height in %.
EDIT3: I did some research, and it seems there is no way to actually get the size of the screen on any device. It's not something the OS can know. When you use a real world unit in CSS it is actually just an estimation based on some properties of your screen. Needless to say that this is not accurate at all.
Not tested, but instead of playing an audio file and check the balance, it could work to listen to the microphone, extract the background noise, and compute its "color" (frequency graph). If IPad Mini has a different microphone model than IPad 2, then their background color should be measurably different and some audio fingerprinting techniques might help you tell which device is in use.
I don't seriously think it could be feasible and worth the hassle in this specific case, but I think fingerprinting the background noise could be used in some apps, for example to tell you where you are when you are inside a building.
Based on Douglas question about new webkitAudioContext().destination.numberOfChannels
on iPad 2 I decided to run some tests.
Checking numberOfChannels returned 2
on iPad mini but nothing on iPad 2 with iOS 5 and 2
as well with iOS 6.
Then I tried to check if webkitAudioContext is available
var hasWebkitAudio = typeof(webkitAudioContext) === "object"; alert(hasWebkitAudio);
Same here iPad Mini and iPad 2 with iOS 6 returns true while iPad 2 with iOS 5 returns false.
(This test don't work on desktop, for desktop check if webkitAudioContext is a function).
Here's the code for you to try out: http://jsfiddle.net/sqFbc/
What if you created a bunch of 1"x1" wide divs and appended them one by one to a parent div until the bounding box jumped from 1 inch to 2 inches? An inch on the mini is the same size as an inch on the iPad, right?
In iOS7 there is a system-wide setting user can tweak: when things become too small to read, Text Size setting can be changed.
That text size can be used to form UI of plausible dimensions, eg for a button (tested on iPad Mini Retina to react to Text Size setting changes):
padding: 0.5em 1em 0.5em 1em; font: -apple-system-body;
( sample button CSS, thanks to jsfiddle and cssbuttongenerator)
I am detecting the iPad mini by creating a canvas that is larger an iPad mini can render , filling a pixel then reading the color back out. The iPad mini reads the color as '000000'. everything else is rendering it as the fill color.
Partial code:
function rgbToHex(r, g, b) { if (r > 255 || g > 255 || b > 255) throw "Invalid color component"; return ((r << 16) | (g << 8) | b).toString(16); } var test_colour = '8ed6ff'; working_context.fillStyle = '#' + test_colour; working_context.fillRect(0,0,1,1); var colour_data = working_context.getImageData(0, 0, 1, 1).data; var colour_hex = ("000000" + rgbToHex(colour_data[0], colour_data[1], colour_data[2])).slice(-6);
I need this for canvas sizing so it's feature detection in my use case.