我有我的问题的简化再现这里。
当浏览器进行计算以查看锚定元素是否适合给定空间然后移动它时,我的 JS 仍然返回元素移动之前的原始坐标。
我尝试使用向我建议的requestAnimationFrame(),但这也无法按预期工作。
我是否正确使用它,或者是否可以使用其他方法在浏览器呈现后运行我的脚本?
您会注意到前几个 div 上的一个红色三角形都跟随鼠标指针,直到它移动到不同的 div。当您到达一个 div 时,浏览器确定没有足够的空间容纳弹出窗口,然后将其移动到其他位置,您会注意到三角形点仍将使用弹出窗口在其原始位置时的坐标。
const hoverTrigger = document.querySelectorAll(".menu");
let currentHoverElement;
function handleMousemove(event) {
const mouseX = event.clientX;
const mouseY = event.clientY;
hoverTrigger.forEach((element) => {
if (element.matches(":hover")) {
requestAnimationFrame(() => {
const boundingRect = element.getBoundingClientRect();
const elementY = Math.round(boundingRect.y);
const offsetY = mouseY - elementY;
if (mouseX === 0 || mouseX <= boundingRect.width) {
element.style.setProperty("--x", mouseX + "px");
element.style.setProperty(
"--w",
boundingRect.width / 2 + mouseX + 16 + "px"
);
}
if (mouseY === elementY || mouseY <= elementY + boundingRect.height) {
element.style.setProperty("--y", offsetY + "px");
}
currentHoverElement = element;
});
}
});
}
function handleMouseleave(event) {
if (currentHoverElement) {
currentHoverElement.style.setProperty("--x", "0");
currentHoverElement.style.setProperty("--y", "-24px");
currentHoverElement.style.setProperty("--w", "100%");
}
}
document.addEventListener("mousemove", handleMousemove);
document.addEventListener("mouseleave", handleMouseleave);
@position-try --custom-bottom {
top: unset;
bottom: anchor(bottom);
}
:root {
--size: 60px;
}
body {
padding: 0;
margin: 0;
background: #333;
}
#sidebar {
width: var(--size);
height: 100dvh;
background: white;
display: grid;
grid-template-rows: repeat(6, 1fr);
gap: 2px;
}
.menu {
--x: 0;
--y: 24px;
--w: 100%;
width: var(--size);
background: #666;
position: relative;
}
.menu:hover > .sub {
visibility: visible;
}
.sub {
position: fixed;
width: calc(var(--size) * 2);
height: calc(var(--size) * 4);
background: #999;
visibility: hidden;
left: calc(anchor(right) + 16px);
top: anchor(top);
position-try: most-height --custom-bottom;
}
.sub:before {
content: "";
height: 100%;
position: absolute;
right: 100%;
top: 0;
width: var(--w);
clip-path: polygon(var(--x) var(--y), 100% 0px, 100% 100%);
background: red;
}
<div id="sidebar">
<div class="menu" style="anchor-name: --a-1">
<div class="sub" style="position-anchor: --a-1">1</div>
</div>
<div class="menu" style="anchor-name: --a-2">
<div class="sub" style="position-anchor: --a-2">2</div>
</div>
<div class="menu" style="anchor-name: --a-3">
<div class="sub" style="position-anchor: --a-3">3</div>
</div>
<div class="menu" style="anchor-name: --a-4">
<div class="sub" style="position-anchor: --a-4">4</div>
</div>
<div class="menu" style="anchor-name: --a-5">
<div class="sub" style="position-anchor: --a-5">5</div>
</div>
<div class="menu" style="anchor-name: --a-6">
<div class="sub" style="position-anchor: --a-6">6</div>
</div>
</div>
我意识到我的错误是我只考虑了悬停元素的坐标,实际上根本没有使用弹出坐标。我会再玩一下这个,并用我想出的解决方案更新我的答案。