【问题标题】:Show popup on mouse location在鼠标位置显示弹出窗口
【发布时间】:2022-01-13 02:42:49
【问题描述】:

我无法在鼠标点击的确切位置弹出一个弹出窗口。 我希望能够单击一个 DIV(位于表格单元格内)并在单击此 div 时显示一个弹出窗口。

现在我的弹出窗口正在工作,但是无论我尝试什么,弹出 DIV 都在页面的中间。

HTML

<ul class="customdropdown" style="display:none;" id="xxx<?php echo $fetch['unit_no']; ?>" role="menu" aria-labelledby="menuitems">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#"</i>Link 1</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#"</i>Link 2</a></li>

</ul>

JQUERY

$(document).ready(function () {
        $('#myDiv<?php echo $fetch['unit_no']; ?>').click(function (e) {
            var myDiv = document.getElementById('myDiv<?php echo $fetch['unit_no']; ?>');
            var leftx = e.pageX-myDiv.offsetLeft;
            var topy = e.pageY-myDiv.offsetTop;

            $("#xxx<?php echo $fetch['unit_no']; ?>")
                .css({
                    position: 'absolute',
                    left: leftx,
                    top: topy,
                    display: 'block'
                })
           
        });
    });

下面发生的截图:

这和DIV的定位有关吗?

【问题讨论】:

  • 为什么你有未关闭的&lt;a元素?

标签: javascript html jquery


【解决方案1】:

这取决于您的弹出窗口是absolute 还是fixed 并且父级设置了static 以外的任何position,以及弹出窗口是否在包装器内;或body 的直系子代。

前面三个例子:

  1. 绝对弹出窗口作为非静态父级的子级(优点和缺点
  2. 固定弹出窗口(各有利弊
  3. 绝对弹出作为文档&lt;body&gt; 的直接子级(最佳

1。将绝对子级移动到父级内的 X、Y 坐标

案例:position: absolute;position: relative; 父级中弹出。

  • 如果父级有滚动条overflow 值不是visible
X = Event.pageX + Parent.scrollLeft - Parent.offsetLeft
Y = Event.pageY + Parent.scrollTop - Parent.offsetTop
  • 如果父级没有滚动条(不要使用这个!):
// !! Bad practice !!
X = Event.pageX - Parent.offsetLeft   
Y = Event.pageY - Parent.offsetTop    

例子:

const EL = (sel, el) => (el||document).querySelector(sel);

const EL_area  = EL("#area");
const EL_popup = EL("#popup");

const showPopup = (evt) => {
  const EL_btn = evt.currentTarget;
  
  Object.assign(EL_popup.style, {
    left: `${evt.pageX + EL_btn.scrollLeft - EL_btn.offsetLeft}px`,
    top:  `${evt.pageY + EL_btn.scrollTop - EL_btn.offsetTop}px`,
    display: `block`,
  });
};

EL_area.addEventListener("click", showPopup);
body {
  height: 300vh; /* Just to force some scrollbars */
}

#area {
  position: relative;  /* this is needed! */  
  height: 150px;
  background: #eee;
  margin: 40px;
}

#popup {
  position: absolute;
  height: 30px;
  background: gold;
  display: none;
}
<div id="area">
  Click here to shop popup, and scroll the window
  <div id="popup">Popup</div>
</div>

优点:

  • 即使页面被滚动,弹出窗口仍然保持在包装元素内

缺点:

  • 如果他是实际的事件target,则需要额外的代码来防止弹出窗口移动 - 以允许与内部内容进行交互并且弹出窗口不移动。
  • 弹出窗口需要是特定父元素的子元素,这会导致弹出窗口和代码可重用性差。 PS:解决方案将使用:SomeClickedElement.append(EL_popup)
  • 包装父元素(#area)需要有一个position 集(static 除外),即:position: relative;

2。将固定元素移动到 X,Y 坐标

案例:position: fixed; 在父级外部(或内部)弹出,但通常作为&lt;body&gt; 的子级。

X = Event.clientX  
Y = Event.clientY

例子:

const EL = (sel, el) => (el||document).querySelector(sel);

const EL_area  = EL("#area");
const EL_popup = EL("#popup");

const showPopup = (evt) => {
  Object.assign(EL_popup.style, {
    left: `${evt.clientX}px`,
    top: `${evt.clientY}px`,
    display: `block`,
  });
};

EL_area.addEventListener("click", showPopup);
body {
  height: 300vh; /* Just to force some scrollbars */
}

#area {
  /* position: relative; /* not necessary any more */
  height: 150px;
  background: #eee;
  margin: 40px;
}

#popup {
  position: fixed;
  height: 30px;
  background: gold;
  display: none;
}
<div id="area">
  Click here to shop popup, and scroll the window
</div>

<div id="popup">Popup fixed</div>

优点:

  • 如果放置在父级 (#area) 的外部 - 如果在其内部发起点击,则无需额外的代码来防止其移动。
  • 更好的代码可重用性。根据点击的元素,您只需更改其内容即可重复使用相同的弹出窗口。
  • 包装父元素 (#area) 不需要有 position
  • 只需 Event.clientXEvent.clientY 即可将其移动到新位置。

缺点:

  • 如果页面滚动,弹出位置相对于窗口是固定的。一个解决方案是让它在页面滚动时隐藏,或者更复杂 - 通过坐标的变化来移动它。

3。 (最好!)将绝对(in-body)元素移动到 X、Y 坐标

案例:position: absolute; popup 作为body 的直接子级

X = Event.clientX + window.scrollX
Y = Event.clientY + window.scrollY

例子:

const EL = (sel, el) => (el||document).querySelector(sel);

const EL_area  = EL("#area");
const EL_popup = EL("#popup");

const showPopup = (evt) => {
  Object.assign(EL_popup.style, {
    left: `${evt.clientX + window.scrollX}px`,
    top: `${evt.clientY + window.scrollY}px`,
    display: `block`,
  });
};

EL_area.addEventListener("click", showPopup);
body {
  height: 300vh; /* Just to force some scrollbars */
}

#area {
  /* position: relative; /* not necessary any more */
  height: 150px;
  background: #eee;
  margin: 40px;
}

#popup {
  position: absolute;
  height: 30px;
  background: gold;
  display: none;
}
<div id="area">
  Click here to shop popup, and scroll the window
</div>

<div id="popup">Popup fixed</div>

优点:

  • 即使页面滚动,弹出位置也会“锚定”在相对于文档的相同位置,而不是滚动窗口。
  • (除非 Event.currentTarget 是整个"body")如果单击其内容,弹出窗口不会改变位置。

针对所有情况的建议:

  • 对于改进的 UX(用户体验)“浮动” 弹出窗口,需要额外计算,即确定 剩余可用空间 以适应它没有隐藏部分的窗口(坐标的最小值和最大值以及实际弹出窗口大小和可用窗口宽度、高度)。我把这个留给读者,因为答案很长 - 除非 cmets 明确要求。
  • 如果用户在其外部点击,则需要额外的代码来关闭弹出窗口。这可以通过简单地检查是否单击来实现 - Event.target.closest("#popup") !== EL_popup(如果 true 则关闭弹出窗口)。这有时适用于 上下文菜单,但很少适用于以窗口为中心的 Modals - 它有一个专用的 close 按钮。

最佳实践示例:

const EL = (sel, el) => (el||document).querySelector(sel);

let EL_popup; // To remember the currently active popup: 
const handler_popup = (evt) => {
  // Get clicked target
  const EL_targ = evt.target;
  
  // Clicked a popup, do nothing (Comment this line if not needed)
  if (EL_targ.closest(".popup")) return;

  // Close currently open popup (if any):
  if (EL_popup) EL_popup.classList.remove("is-active");
  
  // Get initiator button
  const EL_btn = EL_targ.closest("[data-popup]");
  
  // Not a valid button
  if (!EL_btn) return;
  
  // Get the popup
  EL_popup = EL(EL_btn.dataset.popup);  
  
  // No matching popup in this page, do nothing
  if (!EL_popup) return; 

  // Show popup
  Object.assign(EL_popup.style, {
    left: `${evt.clientX + window.scrollX}px`,
    top: `${evt.clientY + window.scrollY}px`,
  });
  EL_popup.classList.add("is-active");
  
};

EL("body").addEventListener("click", handler_popup);
body {
  min-height: 300vh;
}

#area {
  background: #eee;
  padding: 10px;
}

.popup {
  position: absolute;
  background: gold;
  display: none;
}
.popup.is-active {
  display: block;
}
<div id="area" data-popup="#popup-one">Show "popup one"</div>

<button data-popup="#popup-two" type="button">Show "popup two"</button>

<br>Click anywhere to close an open popup  
<br>Click inside a popup. It will not close ()

<div class="popup" id="popup-one">Popup one!</div>
<div class="popup" id="popup-two">Popup TWO!</div>

【讨论】:

  • 谢谢,我使用了选项 3,现在效果很好。
  • 感谢 Gesset 的好消息,不客气!
【解决方案2】:

如果您希望在鼠标点击的确切位置获得弹出窗口,您实际上只需要知道鼠标在窗口中点击的位置。您的点击侦听器已经针对 DIV,因此这只会在该区域注册点击,因此您可以使用 event.clientX 和 event.clientY 来获取指针位置。

$('#myDiv').click(function (event) {

  $("#xxx").css({
    left: event.clientX,
    top: event.clientY,
    display: 'block'
  });

});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-03
    • 1970-01-01
    • 2016-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-14
    • 2014-01-24
    相关资源
    最近更新 更多