我几年前发布了关于 jQuery UI 的 position 功能的文章,但我最近才想到该功能的碰撞检测部分有多么有用。 简而言之:您可以将元素放置在您想要的位置,但如果它计算出您放置的位置会超出屏幕或以其他方式隐藏,它将调整定位以修复它。
这是一个来自 Disqus 的示例,其中此用户弹出窗口的默认设置是向上打开,但如果它会被屏幕顶部隐藏,则会改为向下打开。

我最近在 CodePen 上做了同样的事情,以确保设置下拉区域不会在页面底部边缘下方打开,而是向上打开。

无论何时页面上的元素以方向性打开,并且您不能 100% 确定该方向不会被隐藏,碰撞检测都是一个好主意。
工具提示是一个经典的例子。 您可能设计了一个工具提示,使其在链接的上方和右侧打开。
$("a[data-tooltip]")
.on("mouseenter", function() {
var whichTip = $(this).data("tooltip");
$(".tooltip[data-tooltip=" + whichTip + "]")
.position({
my: "left bottom",
at: "left top",
of: $(this)
})
.show();
});
(附带说明,如果我们能够以某种方式使用 HTML 在其中创建工具提示而无需 JS,那不是很好吗?)

但是,如果该链接靠近页面顶部,它很容易在边缘上方打开,并且非常无用。

此外,根据其设计方式,它也可能在边缘附近存在危险。

jQuery UI 实际上默认情况下会启用碰撞检测,并且它会“翻转”,这意味着
将元素翻转到目标的另一侧,然后再次运行碰撞检测以查看它是否适合。 将使用允许更多元素可见的一侧。
如果您想要关闭它,则必须明确关闭它。 碰撞还有其他几个值,包括 fit
(它会轻微调整位置,直到元素适合页面/区域),或 fitflip
(它会先翻转,然后根据需要进行调整)。
使用 jQuery UI position,它将如下所示。
$("a[data-tooltip]")
.on("mouseenter", function() {
var whichTip = $(this).data("tooltip");
$(".tooltip[data-tooltip=" + whichTip + "]")
.position({
my: "left bottom",
at: "left top",
of: $(this),
collision: "flipfit"
})
.show();
});
现在,如果工具提示将打开并被顶部或边缘隐藏,它将翻转或移动以适应。

它是如何工作的? 数学!
我相信您可以想象它是如何工作的。 JavaScript 知道所有元素以及视口本身的尺寸和位置。 因此,它可以进行一些检查,例如:如果一个特定尺寸的元素位于这个位置,它是否适合这个区域?
如果您不想使用 jQuery UI,您当然可以自己编写。 如果您这样做,我可能建议的一件事是:在元素翻转或调整大小后向其添加类名。 jQuery UI 目前缺少这一点,您可能需要这些类名来影响工具提示中的其他元素。 例如,确保指针箭头指向正确的位置。
简单演示
碰撞检测针对的容器不必是视口,它可以是指定的容器。 这里就是这种情况,仅用于演示。
查看 Chris Coyier 在 CodePen 上的笔 碰撞检测(@chriscoyier)。
以及隐藏工具提示的 JS。
$("a[data-tooltip]")
.on("mouseenter", function() {
var whichTip = $(this).data("tooltip");
$(".tooltip[data-tooltip=" + whichTip + "]")
.position({
my: "left bottom",
at: "left top",
of: $(this),
collision: "flip",
within: ".page-wrap"
})
.show();
})
.on("mouseleave", function() {
var whichTip = $(this).data("tooltip");
$(".tooltip[data-tooltip=" + whichTip + "]")
.stop()
.fadeOut(function() {
$(this).removeAttr("style");
});
});
这在 Codepen 上是实时的吗? 如果是这样,它对我不起作用。 我经常将窗口调整为奇怪的短尺寸,无法访问菜单,因此这将非常棒。
您最近尝试过吗? 它有一段时间存在问题,但现在已修复。
它应该可以工作。 主要是在编辑器处于左侧或右侧模式并且设置将在页面底部下方打开但上方有空间时,但碰撞检测的功能有限=)。 如果您认为它应该工作但没有工作,请随时 联系支持。
谢谢 Chris,我会给支持发送消息。
这与悬停事件有什么不同? 在此应用程序中,似乎没有太大区别。 在 3D CSS 中,碰撞更有意义。
碰撞检测与悬停相关,因为如果悬停事件显示了一个元素,但该显示元素的位置被隐藏或被截断,那么了解这一点(碰撞检测)会很好,以便您可以将其移动到未被隐藏或截断的位置。
很高兴能获得提示或提醒“工具箱中的另一个工具”。 谢谢,Chris。
如果它位于一个 iframe 内部,该 iframe 本身足够大,因此不需要滚动,但其包含的页面足够小,以至于该 iframe 中的元素可能会被部分隐藏,该怎么办?
实际上,这个东西很酷! 但是,在 codepen 中,如果我们调整窗口大小,弹出窗口(信息)将始终在那个小设置图标的底部打开!
我在 Firefox 中测试过!
也许尝试刷新缓存或其他操作。 这是我的 Firefox:http://cl.ly/YUj4
如果在您认为它应该工作但没有工作的地方,请随时 联系支持。 屏幕截图和详细的浏览器信息将非常有用。
是的,Chris! 好的! (我还会检查 Chrome 和 IE 的最新版本!)
嗨,Chris,
我是 jQuery UI 团队的 TJ。 感谢您的撰写。 仅供参考,您可以使用
using
属性相对轻松地获得您正在寻找的 CSS 类名。 以下是如何使用该属性为箭头设置样式的示例:http://jsfiddle.net/tj_vantoll/587n9/。上周我为一些弹出窗口自己编写了一个。 我甚至都不知道 JQuery UI 有这种功能! 当您想设置并快速完成时,这非常酷 :)
我越深入研究,就越想要另一个 CSS 规则来处理此类绝对定位的元素,例如
而这些项目的缩放将是 CSS 中的另一个不错的功能……:-)
另一种方法是使用像 :validate 这样的选择器,例如
这对所有 GUI 开发人员来说将是一个非常棒的功能……
这在 codepen 上效果很好(我看到您也处理了其他事情,谢谢)。