d3.js 隐藏不透明度的弹出窗口不能与指针事件一起正常工作

Posted

技术标签:

【中文标题】d3.js 隐藏不透明度的弹出窗口不能与指针事件一起正常工作【英文标题】:d3.js hiding popups with opacity not working properly with pointer events 【发布时间】:2021-10-15 10:36:16 【问题描述】:

我在 d3 中有一张地图,上面覆盖了点。我希望用户能够单击这些点并弹出一个可滚动的弹出窗口。然后当用户点击关闭(身体上的任何地方)时,我希望弹出窗口消失。鼠标悬停也是如此 - 鼠标悬停时显示弹出窗口,鼠标悬停时隐藏。

这是网站:https://shmoss.github.io/Town_Sounds/#

我的问题:

我的代码在桌面以及我的 iPhone 11 上运行良好。但是,在 其他 iPhone 上测试时,如果我打开一个弹出窗口,请单击关闭,然后重新单击另一个,弹出窗口被冻结。它不滚动,即似乎指针事件被禁用。底部有视频。

这是我的代码,尽量简洁:

//build d3 events (circles)
var events = mapG.selectAll("circle")
        .data(eventArray)
        .enter().append("circle")
        .style("class", 'events')
        .on("mouseover", function(d)  

            //add popup - set opacity to make visible
            LeafletDiv.transition()        
                .duration(200)      
                .style("opacity", .9)
                .style("scrollTop", 0)


                var popInfo = '<br>' + d.Venue + '<br>' 

                LeafletDiv
                .html(popInfo)
                .style("top", "1.5vh")
                .style("text-align", 'left')

        
       
    //on-click event
    .on("click", function(d)  
        $('body').css(
            overflow: 'hidden'
        );

        //disable hover event listeners
        d3.selectAll(".events").on("mouseout", null);
        d3.selectAll(".events").on("mouseover", null);

        //add popup   
        var value2014 = currentMap.get(d.location);  

        LeafletDiv.transition()        
            .duration(200)      
            .style("opacity", .9);

                selections = d3.selectAll(".events").filter(function(d)

                return d.Date == this_date 

                )

                //populate html for popup
                var appendText = []
                selections.each(function(d)

                var popInfo = '<br>' + d.Venue + '<br>'                   
                appendText.push(popInfo+ '<br/>' + '<br/>')
              
                )
            //append html to popup                 
            LeafletDiv
                .html( appendText.join(""))
                .style("top", "1.5vh")
                .style("text-align", 'left')
                .style("pointer-events", 'auto')
          

        $('.county2014Tooltip').scrollTop(0);

        d3.event.stopPropagation();

        // if user clicks a SECOND time, anywhere, make popup disappear
        d3.select("body").on("click", function(d)  
            console.log("clicking off popup")

                //hide popup
                var elements = d3.select(LeafletDiv)
                elements.scrollTop = 0
       
                LeafletDiv.transition()        
                    .duration(200)      
                    .style("opacity", 0)
                    .style("pointer-events", 'none') 
                    .attr("scrollTop", 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)  
                    //mousing out, hide popup!     
                    LeafletDiv.transition()        
                        .duration(200)      
                        .style("opacity", 0);        
                    )

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

                    LeafletDiv .html('<br>' + d.Venue + '<br>'
                    )
                        .style("top", "1.5vh")
                        .style("text-align", 'left')

                )
                      
        )
    )

    //on mouseout, hide popup
    .on("mouseout", function(d)        
        LeafletDiv.transition()        
            .duration(200)      
            .style("opacity", 0)
            .style("scrollTop", 0)  
    )

记录行为的视频:

一部 iPhone 11(完全相同的代码,但按预期工作):

https://www.youtube.com/watch?v=_3MA4bJYiYM

其他 iPhone 11(完全相同的代码,不工作:)

https://www.youtube.com/watch?v=OfbboDnIw1E

我的尝试:

出于某种原因,使用持续时间为200 ms 的转换scale(0) 有效。作为当前不透明度方法的替代方法,这项工作。但它看起来不专业,我很困惑为什么上面的代码不能通用。

【问题讨论】:

【参考方案1】:

如果您使用 Leaflet 并且只需要圆圈和弹出窗口,则可以使用来自传单本身的 circleMarker 和弹出窗口。它可能比 d3 更容易实现。

https://leafletjs.com/reference-1.7.1.html#circlemarker

https://leafletjs.com/reference-1.7.1.html#popup

您可以使用 css 获得所需的所有样式/过渡。

【讨论】:

以上是关于d3.js 隐藏不透明度的弹出窗口不能与指针事件一起正常工作的主要内容,如果未能解决你的问题,请参考以下文章

js的事件冒泡和点击其他区域隐藏弹出层

如何在 Qt 中的弹出窗口小部件上创建平滑的圆角

带有视觉跟踪弹出视图的 UISlider。隐藏在其他视图元素后面的弹出窗口

c# 获取移动硬盘信息监听移动设备的弹出与插入事件

用于处理应用程序中的弹出窗口的 Web 浏览器

jquery怎么点击弹出上传选项?