有没有办法检测浏览器是不是具有亚像素精度?

Posted

技术标签:

【中文标题】有没有办法检测浏览器是不是具有亚像素精度?【英文标题】:Is there a way to detect if the browser has subpixel precision?有没有办法检测浏览器是否具有亚像素精度? 【发布时间】:2012-09-18 06:10:53 【问题描述】:

有没有办法检测浏览器是否对元素具有亚像素精度?

IE9 与其他任何主流浏览器不同,它的元素具有亚像素精度(元素宽度可以是 50.25 像素),因此,我需要区别对待。

一种方法是使用 jQuery 检测浏览器名称和版本,但这在 jQuery 中已弃用且不推荐,而是建议应针对浏览器名称和版本测试功能的存在。

【问题讨论】:

赞成并加注星标,因为我根本不知道亚像素如何工作。 你不能把一个div的样式设置成“50.5px”,然后在javascript中检查它的宽度,onload,看看它是否被四舍五入? 有趣的是,据我所知,IE 是实现亚像素精度的主流浏览器中最后一个的(或者我们在谈论两个不同的东西;))。 @Yoshi 也许是为了别的,但是对于元素的尺寸,所有其他主流浏览器都有整数值。 $Yoshi getComputedStyle 不是指 CSS 值吗?无论如何,我认为这是一个更复杂的问题,考虑到浏览器内部查看值的方式、您对显示的观点、josh 下面提到的规范以及用户看到的实际显示尺寸。我想还有更多需要了解和搜索的内容。然而,事实仍然是,IE9 处理它的方式有所不同,但要正确理解它,还有更多需要搜索的内容。 【参考方案1】:

您可以创建一个奇数大小的容器并将两个 50% 宽度的元素放入其中,然后查看它们是否已按 50:50 拆分。

见http://jsfiddle.net/alnitak/jzrQ6/

它在 MacOS X 10.8.2 上的 Chrome 22.0.1229.79 上返回 false,在 Firefox 15.0.1 上返回 true。我没有 MSIE 来测试它。

【讨论】:

我在 Firefox 和 IE10 中得到 true Chrome 22.0.1229.79 m 在 Win 7 上 在 Chrome 中,我在 50% 到 149% 之间的缩放级别上得到错误,而在该范围之外的许多(但不是全部)缩放级别上是正确的。 @josh3736 有趣的发现! jsfiddle.net/KAW3d/1 - 在 IE6 和 IE7 中 100.5px + 100.5px = 200px(两个 100.5px 浮点数适合 200px 容器),在 IE8+ 中 100.5px + 100.5px > 200px【参考方案2】:

我不知道你从哪里知道 IE9 是唯一支持小数像素单位的浏览器,但这种假设是完全错误的。

来自section 4.3 of the spec(已添加重点):

长度值的格式(在本规范中用 表示)是一个 (带或不带小数点)紧跟一个单位标识符(例如,px、em 等)。

并定义

某些值类型可能具有整数值(由 表示)或实数值(由 表示)。实数和整数仅以十进制表示法指定。 由一个或多个数字“0”到“9”组成。 可以是 ,也可以是零个或多个数字,后跟一个点 (.),后跟一个或多个数字。整数和实数前面都可以用“-”或“+”表示符号。 -0 等价于 0,不是负数。

因此,根据规范,px 长度单位必须支持小数。

为了证明这一点,请查看fullscreen 中的this fiddle 并使用浏览器的缩放功能一直放大:

在这个 Chrome 屏幕截图中,请注意 5.5px 的蓝色框确实比 5px 的红色框要高。


我认为混淆可能源于以下事实:非标准 element.clientHeight 返回计算的(四舍五入)整数值,并且舍入在不同情况下的发生方式不同浏览器。

在我的小提琴中,对于蓝色 <div>clientHeight,IE9 和 Firefox 15 在 100% 缩放时给出 6。 Chrome 22 和 Opera 12 提供5。在所有浏览器中,该属性的值都会随着用户更改浏览器的缩放级别而变化。

换句话说,它是不可靠的。

如果您想使用元素的实际分数单位进行计算,请使用getComputedStyle

var el = $('#b')[0]; // the actual DOM element
var height = parseFloat(getComputedStyle(el).height); // => 5.5

【讨论】:

我与 Yoshi 进行了更长的讨论,但在您的示例中,如果您使用开发人员工具查看 Properties - htmlDivElement - clientWidth 中元素的客户端设置,它将显示整数值。你知道这是为什么吗? clientWidth/clientHeight 是非标准属性,在所有浏览器中总是返回整数(换句话说,舍入)值。在updated fiddle 中,请注意clientHeight 的值会随着您更改浏览器的缩放级别而波动。 问题的核心是 IE9 和其他浏览器处理显示的方式之间的差异,特别是在我的情况下,相同的布局在 IE9 中的显示与其他浏览器不同,我认为这是一个问题IE9处理亚像素精度的方式。从您的帖子以及与 Yoshi 的讨论中,我了解到这个问题还有更多内容需要搜索,并了解每个浏览器处理此问题的方式之间的差异。您的帖子非常有用,有助于得出这个结论,您的解决方案也很有帮助。【参考方案3】:

http://jsfiddle.net/KAW3d/1/

在 IE6、IE7 和 Opera 12.02 中:100.5px + 100.5px = 200px(两个 100.5px 的浮点数适合 200px 的容器) 在 IE8+、Firefox 15.0.1、Chrome 22 中:100.5px + 100.5px > 200px

【讨论】:

【参考方案4】:

最近我们不得不进行一些严格的像素完美计算,我需要检查浏览器是否会支持亚像素布局。我使用其他一些答案作为指南创建了一个用于Conditionizr 或Modernizr 的测试:

conditionizr.add('subpixel-layout', function() 
    var $testWrap = $(
        '<div style="width: 4px; height: 2px; position: absolute; right: 0; bottom: 0;">' +
            '<div id="subpixel-layout-1" style="width: 2.5px; height: 1px; float: left;"></div>' +
            '<div id="subpixel-layout-2" style="width: 2.5px; height: 1px; float: left;"></div>' +
        '</div>'
    ).appendTo('body');

    var supported = $('#subpixel-layout-1').position().top !== $('#subpixel-layout-2').position().top;
    $testWrap.remove();
    return supported;
);

然后你可以使用:

conditionizr.on('!subpixel-layout', function () 
    // subpixel layout is NOT available
);

你应该可以在 Modernizr 中使用 Modernizr.addTest() 做同样的事情,但我没有测试它。

显然我在这里使用jQuery,但如果没有它也应该很简单。

【讨论】:

以上是关于有没有办法检测浏览器是不是具有亚像素精度?的主要内容,如果未能解决你的问题,请参考以下文章

亚像素数值极值检测算法总结

具有亚像素精度的图像处理

Qt + opencv 角点检测(Shi-Tomas + 亚像素精度角点)

图像边缘检测基于matlab Zernike矩亚像素边缘检测含Matlab源码 1536期

OpenCV亚像素级的角点检测

浏览器是不是支持 getBoundingClientRect 的宽度和高度属性?