【问题标题】:How to trigger click of both elements, when clicking overlapping area单击重叠区域时如何触发两个元素的单击
【发布时间】:2020-04-11 19:41:04
【问题描述】:

我有两个相互重叠的元素,两者都有点击事件。单击每个元素都可以正常工作。

如果我点击如下图的重叠区域,是否可以同时触发两者的点击?

下面是我的代码

$("#circle1").click(function(d) {
  alert("circle1");
});
$("#circle2").click(function(d) {
  alert("circle2");
});
.path {
  fill: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width="525" height="226">
   <circle id="circle1" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
   <circle id="circle2" cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="transparent" />
</svg>

【问题讨论】:

  • 如果您有某种方法可以确定点击是在公共区域上,您可以直接致电 $( "#circle2" ).trigger( "click" ); 这不是正确的方法,只是我脑海中的一个想法

标签: javascript css d3.js svg dom-events


【解决方案1】:

我会使用剪辑路径来获得 2 个圆圈的交点。然后我会将事件附加到交叉点。

intersection.addEventListener("click",()=>{
  console.log("intersection")
})
circle{stroke-width:3;stroke:black;}
svg{border:1px solid}
<svg id="svg" viewBox="0 0 525 226">
  <defs>
   <circle id="circle1" cx="50" cy="50" r="40" />
   <circle id="circle2" cx="80" cy="50" r="40"  />
   <clipPath id="clip"><use xlink:href="#circle2"  />
</clipPath>  
  </defs>
  <use xlink:href="#circle1" class="circle"  fill="red" /> 
  <use xlink:href="#circle2" class="circle"  fill="transparent" />

  <use xlink:href="#circle1" id="intersection" clip-path="url(#clip)"  fill="gold" />
</svg>

【讨论】:

  • 漂亮的解决方案!
【解决方案2】:

您不应依赖任何计算交叉点位置或创建另一个元素的方法来计算交叉点。这样的方法最终会失败,或者变得过于复杂和繁琐。

取而代之的是,使用事件本身和document.elementFromPoint 之类的方法来获取点击下的所有元素。例如,您可以“递归地”使用document.elementFromPoint,如here 所述。然后,使用selection.dispatch,将点击事件分派给点击下的所有元素。

这是一个非常基本的演示(点击蓝色圆圈、红色圆圈或交叉点):

let clicked;
d3.select(".blue").on("click", function() {
  if (!clicked) return;
  console.log("blue circle were clicked")
});
d3.select(".red").on("click", function() {
  if (!clicked) return;
  console.log("red circle were clicked")
});
d3.select("svg").on("click", function() {
  clicked = true;
  getAllElements(...d3.mouse(this));
  clicked = false;

  function getAllElements(x, y) {
    const elements = [];
    let thisElement = document.elementFromPoint(x, y);
    while (thisElement && thisElement.nearestViewportElement) {
      elements.push(thisElement);
      d3.select(thisElement).style("display", "none");
      thisElement = document.elementFromPoint(x, y);
    }
    elements.forEach(function(elm) {
      d3.select(elm).style("display", null)
        .dispatch("click");
    });
  };
})
.as-console-wrapper {
  max-height: 30% !important;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg>
  <circle cx="100" cy="75" r="60" fill="powderblue" stroke="gray" stroke-width="2" opacity="0.75" class="blue"></circle>
  <circle cx="170" cy="75" r="60" fill="tomato" stroke="gray" stroke-width="2" opacity="0.75" class="red"></circle>
</svg>

【讨论】:

    【解决方案3】:

    这是计算重叠区域的方法,计算每个click eventclientX 并确保它是重叠区域,因为您已经为circles 提供了XY。这是示例。例如,我提供了一个粗略的想法,您可以根据实际尺寸进行计算。

    $(".circle").click(function(e) {
        if((event.clientX>50  && event.clientX<80) && (event.clientY>25 && event.clientY<85)){
        alert('overlaper area');
        }
    });
    .path {
      fill: red;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
    <svg width="525" height="226">
       <circle class="circle" id="circle1" cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
       <circle class="circle" id="circle2" cx="80" cy="50" r="40" stroke="black" stroke-width="3" fill="transparent" />
    </svg>

    【讨论】:

    • 如果我没记错的话,您的代码将覆盖一个与重叠区域不同的矩形区域
    猜你喜欢
    • 2015-12-04
    • 2016-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    相关资源
    最近更新 更多