【问题标题】:Adding second click event listener within a click event listener在单击事件侦听器中添加第二个单击事件侦听器
【发布时间】:2019-10-01 00:00:02
【问题描述】:

我正在尝试使用 D3 在现有的单击事件侦听器中添加第二个单击事件侦听器,但未成功。

基本上,我有一张事件地图(圆圈)。我希望用户能够单击一个圆圈并出现一个弹出窗口。我希望该弹出窗口仅在用户第二次单击任意位置时才消失。因此,单击一个圆圈将实例化弹出窗口并将其绑定,然后再次单击 ANYWHERE 将使弹出窗口消失并将圆圈恢复为仅响应悬停,除非再次单击。

我通过在圆形事件监听器中添加另一个“body”点击事件监听器来解决这个问题:

  // event listener: if events (circles) are clicked, instantiate pop-up
  d3.selectAll(".events").on("click", function(d) { 
        console.log("event clicked!")
         //disable hover event listeners
         d3.selectAll(".events").on("mouseout", null);
         d3.selectAll(".events").on("mouseover", null);              
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)

        // if user clicks a SECOND time, anywhere, make popup disappear
        d3.select("body").on("click", function(d) { 
            console.log("body clicked")
            //hide popup
            popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);  
            //revert back to hover, unless user clicks again!
            d3.selectAll(".events").on("mouseout", true);
            d3.selectAll(".events").on("mouseover", true);
            d3.selectAll(".events").on("mouseout", function(d) { 
            console.log("mousing out!")      
                popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);              
              })

            // mouseover event listers added back in
            d3.selectAll(".events").on("mouseover", function(d) { 
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)

          })            
        })

我的问题是这两个事件是同时触发的,而不是按顺序触发的:一旦我点击了一个圆形事件,body click 事件监听器也被实例化了,所以弹出窗口一被渲染就被删除.有没有办法以类似于我上面描述的方式做我想做的事情?提前致谢。

【问题讨论】:

  • 我们可以得到一些 HTML 以便我可以运行代码吗?

标签: javascript html d3.js event-handling click


【解决方案1】:

点击会冒泡,这是正常预期的。为避免这种情况,请使用event.stopPropagation。你也可以使用d3.events(虽然它们存在......):

d3.event.stopPropagation();

这里是演示,点击矩形及其外:

d3.select("rect").on("click", function() {
  console.log("rectangle clicked");
  d3.event.stopPropagation();
  d3.select("body").on("click", function() {
    console.log("body clicked")
  })
})
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg>
  <rect width="50" height="50" x="100" y="50"></rect>
</svg>

【讨论】:

  • PS:虽然这肯定是重复的,但在搜索了几分钟后我找不到一个好的目标......问题是我知道解决方案,并且因此,虽然 SO 没有答案的搜索机制,但我必须寻找一个解决方案涉及stopPropagation 的问题,这不是一件容易的事。如果有人找到一个好的目标,我会关闭它。
  • Gerardo - 完美,停止传播方法奏效了!谢谢你。还有一个问题:如果我想防止用户单击弹出窗口本身时弹出窗口消失:为什么这样的事情不起作用: if(this !== currentCircle || this !== ('.popup'){ //在这里做一些事情}
  • 基本上,我想知道如何使用弹出类 ('.popup) 上的 d3 类选择器来检查“此”点击是当前圈还是弹出框本身。跨度>
  • 在这种情况下,它将是d3.select(".popup").node()
【解决方案2】:

你可以这样做:

  // event listener: if events (circles) are clicked, instantiate pop-up
  d3.selectAll(".events").on("click", function(d) { 
        console.log("event clicked!")
        const currentCircle = this; 
        //disable hover event listeners
         d3.selectAll(".events").on("mouseout", null);
         d3.selectAll(".events").on("mouseover", null);              
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)
        // if user clicks a SECOND time, anywhere, make popup disappear
        d3.select("body").on("click", function(d) { 
    if(this !== currentCircle){
            console.log("body clicked")
            //hide popup
            popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);  
            //revert back to hover, unless user clicks again!
            d3.selectAll(".events").on("mouseout", true);
            d3.selectAll(".events").on("mouseover", true);
            d3.selectAll(".events").on("mouseout", function(d) { 
            console.log("mousing out!")      
                popup.transition()        
                  .duration(200)      
                  .style("opacity", 0);              
              })

            // mouseover event listers added back in
            d3.selectAll(".events").on("mouseover", function(d) { 
              popup.transition()        
                 .duration(200)      
                .style("opacity", .9);
              popup.html(d.ArtistBio)

          })
       }            
        })

在body事件监听器内部,检查点击的元素是否与当前点击的圆圈/弹出框不同。

【讨论】:

    猜你喜欢
    • 2019-07-05
    • 1970-01-01
    • 2016-10-31
    • 2013-11-08
    • 2021-09-09
    • 2012-06-23
    • 1970-01-01
    相关资源
    最近更新 更多