【问题标题】:How to detect wether the mouse is over the :before or over the :after part of an element如何检测鼠标是否在元素的 :before 或 :after 部分上方
【发布时间】:2018-06-12 21:57:30
【问题描述】:

我有这个 CSS 来定义放置区域,用户可以在其中放置现有部分之前或之后的部分。

.section:before,
.section:after {
    content: "[insert here]";
    height: 64px;
    line-height: 56px;
    width: 100%;
    display: block;
    border: 3px dashed #aaa;
}

这里使用 JavaScript + JQuery 是 drop listener,它检测当前鼠标下的元素:

elem.on('drop', function(e) {
  e.preventDefault();

  var container = $(elem[0].elementFromPoint(e.clientX, e.clientY));
});

但是,container 对于 :before 和 :after 情况将是相同的元素。

我如何才能知道用户是在该部分之前还是之后放弃了?

【问题讨论】:

  • 当然。因为:before:after 有点“在”同一个容器内。
  • 如果你想处理 DOM 事件,你应该使用真实元素,而不是伪元素。

标签: javascript jquery css pseudo-element


【解决方案1】:

::before::after 是 javascript 不知道的 css 伪元素。对于 javascript,它们都是它们的父元素。

您可能想使用真正的 html 元素来做到这一点。

【讨论】:

    【解决方案2】:

    :before 和 :after 不是 DOM 的一部分,因此任何 Javascript 都无法访问它们。

    但是我能想到的唯一解决方案是计算该部分的高度,然后将其与下降 x 和 y 坐标进行比较,以确定它是在之前还是之后下降。

    【讨论】:

    • 比较鼠标位置和元素位置确实有效。 (e.clientY
    • 干杯 :) 是的,这是一个更好的主意。我的回答是因为一些限制你需要这样做
    【解决方案3】:

    我认为你不能操纵伪元素 ::before::after,因为技术上没有 DOM,因此任何 JavaScript 都无法访问。

    【讨论】:

      【解决方案4】:

      这其实是可能的。

      (尽管 - 正如其他人所提到的 - 可能不是最好的主意)

      假设内容堆叠在另一个之上:之前 -> 内容 -> 之后

      我们可以计算相对于容器的放置点,然后 - 基于生成内容的高度,我们可以确定元素是放置在之前区域还是之后区域。

      是的,javascript can actually access css properties of pseudo-elements

      这是通过Window.getComputedStyle()完成的

      语法:(来自MDN

      var style = window.getComputedStyle(element[, pseudoElt]);
      

      pseudoElt 可选

      指定要匹配的伪元素的字符串。 对于常规元素,必须省略(或为 null)。

      因此,例如,获取节之前生成的内容的高度(我们称其为“目标”):

      window.getComputedStyle(target, ':before').height 
      

      这是一个演示 sn-p:

      var elem = document.getElementById("el");
      var target = document.getElementById("target");
        
      var targetHeight = parseFloat(window.getComputedStyle(target).height);
      var beforeHeight = parseFloat(window.getComputedStyle(target, ':before').height);
      var afterHeight = parseFloat(window.getComputedStyle(target, ':after').height);
      
      elem.addEventListener("drag", function(e) {
        document.body.classList.remove('dropped');
      });
      
      target.addEventListener("dragover", function(e) {
        this.textContent = "dragging over section";
        document.body.classList.add('dragging-over');
        addBeforeAfterClasses(e);
      });
      
      target.addEventListener("dragleave", function(e) {
        document.body.classList.remove('dragging-over');
        this.textContent = "section";
        e.currentTarget.style.background = "none";
      });
      
      target.addEventListener("drop", function(e) {
        document.body.classList.add('dropped');
        addBeforeAfterClasses(e);
        this.textContent = "successfully dropped!";
      });
      
      function addBeforeAfterClasses(e) {
        var dropOffsetTopWithRespectToContainer = e.clientY - target.offsetTop;
        if(dropOffsetTopWithRespectToContainer <= beforeHeight) {
          document.body.classList.add('before');
        } else {
          document.body.classList.remove('before');
        }
        if(dropOffsetTopWithRespectToContainer > targetHeight - beforeHeight) {
          document.body.classList.add('after');
        } else {
          document.body.classList.remove('after');
        }
      }
      
      target.ondrop = drop_handler;
      target.ondragover = dragover_handler;
      
      function drop_handler(e) {
        e.preventDefault();
      }
      
      function dragover_handler(e) {
        e.preventDefault();
      }
      .section {
        margin: 10px;
        position: relative;
      }
      .section:before,
      .section:after {
          content: "[insert here]";
          height: 64px;
          line-height: 56px;
          width: 100%;
          display: block;
          border: 3px dashed #aaa;
      }
      
      .dragging-over.before .section:before {
        content: "[drop into before]";
        border-color: green;
      }
      
      .dragging-over.after .section:after {
        content: "[drop into after]";
        border-color: green;
      }
      
      .dropped.before .section:before {
        content: "[dropped into before]";
        background-color: green;
        color: white;
      }
      
      .dropped.after .section:after {
        content: "[dropped into after]";
        background-color: green;
        color: white;
      }
      
      .elem {
        width: 20px;
        height: 20px;
        border-radius: 50%;
        background-color: maroon;
        margin: 0 20px;
        display: inline-block;
      }
      <div id="target" class="section">section</div>
      <span>drag me:</span>
      <div id="el" draggable="true" class="elem"></div>

      Codepen demo

      【讨论】:

        猜你喜欢
        • 2013-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-01
        • 2010-11-19
        • 2019-02-22
        • 2013-11-07
        相关资源
        最近更新 更多