【问题标题】:Prevent mouseout action after click on an element with D3.js使用 D3.js 单击元素后防止鼠标操作
【发布时间】:2016-11-27 06:33:54
【问题描述】:

当用户单击该元素时,我想阻止该元素的鼠标移出操作。示例见JSFiddle(即使我点击标签,圆圈也会消失)。

有没有一种简单的方法可以使用 d3.js 实现我的目标?谢谢!

JSFiddle 示例代码:

var svg = d3.select("#content")
                        .append("svg")
            .attr("width", 600)
            .attr("height", 400);
var g = svg.append("g");
var text = g.append("text")
                            .text("Click me")
              .style("fill", "Blue")
              .attr("x", 50)
              .attr("y", 50)
              .on("mouseover", mouseover)
              .on("mouseout", mouseout)
              .on("click", click);

var circle = g.append("circle")
                                .style("fill", "Orange")
                .attr("cx", 150)
                .attr("cy", 90)
                .attr("r", 15)
                .classed("hide", true)
                .classed("someClass", true);

function mouseover(p){
    d3.selectAll("circle.someClass").classed("hide", false);
}
function mouseout(p){
    d3.selectAll("circle.someClass").classed("hide", true);
}
function click(p){
    d3.selectAll("circle.someClass").classed("hide", false);
}

【问题讨论】:

    标签: javascript d3.js svg onclick mouseout


    【解决方案1】:

    如果您打算只使用一个元素来控制圆圈,请使用“标志”。有条件地注册/取消注册事件不是一个好主意。

    检查你的小提琴的这个更新版本:

    https://jsfiddle.net/cze9rqf7/

    var svg = d3.select("#content")
              .append("svg")
              .attr("width", 600)
              .attr("height", 400);
    var g = svg.append("g");
    var text = g.append("text")
              .text("Click me")
              .style("fill", "Blue")
              .attr("x", 50)
              .attr("y", 50)
              .on("mouseover", mouseover)
              .on("mouseout", mouseout)
              .on("click", click);
    
    var circle = g.append("circle")
              .style("fill", "Orange")
              .attr("cx", 150)
              .attr("cy", 90)
              .attr("r", 15)
              .classed("hide", true)
              .classed("someClass", true);
    
    var isClicked = false;
    
    function mouseover(p){
        d3.selectAll("circle.someClass").classed("hide", false);
    }
    
    function mouseout(p){
        if(!isClicked) {
            d3.selectAll("circle.someClass").classed("hide", true);
        }
    }
    
    function click(p){
        isClicked = !isClicked;
        d3.selectAll("circle.someClass").classed("hide", false);
    }
    

    编辑评论

    如果您需要“记住”每个元素的状态,而不是使用全局,您应该对这些元素使用数据绑定:

    var text = g.append("text")
      .datum({isClicked: false})
      .text("Click me")
      ...
    
    function mouseout(p){
        // p is the data-bound object
        if(!p.isClicked) {
            var className = d3.select(this).attr("class");
            d3.selectAll("circle."+className).classed("hide", true);
      }
    }
    
    function click(p){
        // on click edit the data-bound object
        p.isClicked = !p.isClicked;
        var className = d3.select(this).attr("class");
        d3.selectAll("circle."+className).classed("hide", false);
    }
    

    更新小提琴here

    【讨论】:

    • 是的,你的解决方案也是我的解决方案。问题是我有很多标签,每个标签控制一些不同的元素(线、圆)。所以我想单击一个元素并防止该元素的鼠标移出,但是如果发生鼠标悬停(无需单击),则鼠标移出应该可以正常工作。使用标志不会发生这种情况,我可能需要为每个标签设置一个标志。但我希望有更好的解决方案
    • 检查这个小提琴看看我在说什么:jsfiddle.net/0n6fx9jy/11
    • @GioBact,如果您需要“记住”每个元素的状态,您应该在这些元素上使用数据绑定。更新了您的example here
    • 感谢@Mark 的回答。这很有帮助。我有一个问题,即使没有事件也可以检索基准信息,所以没有p。我的意思是,如果我尝试做这样的事情:d3.select("text.someClass").isClicked? 我得到undefined 结果。我也尝试了一些不同的语法,我检查了文档但不明白。
    • @GioBact,语法为d3.select("text.someClass").datum(),返回Object {isClicked: false}
    【解决方案2】:

    这是一个没有任何“标志”的答案:

    鉴于您有许多标签,一种选择是删除被点击元素的mouseout

    d3.select(this).on("mouseout", null);
    

    这是你更新的小提琴:https://jsfiddle.net/gerardofurtado/38p18pLt/

    和 Stack sn-p 中相同的代码:

    var svg = d3.select("body")
      .append("svg")
      .attr("width", 600)
      .attr("height", 400);
    var g = svg.append("g");
    var text = g.append("text")
      .text("Click me")
      .style("fill", "Blue")
      .attr("x", 50)
      .attr("y", 50)
      .classed("someClass", true)
      .on("mouseover", mouseover)
      .on("mouseout", mouseout)
      .on("click", click);
    
    var text2 = g.append("text")
      .text("Click me")
      .style("fill", "Blue")
      .attr("x", 50)
      .attr("y", 150)
      .classed("someClass2", true)
      .on("mouseover", mouseover)
      .on("mouseout", mouseout)
      .on("click", click);
    
    var circle = g.append("circle")
      .style("fill", "Orange")
      .attr("cx", 150)
      .attr("cy", 90)
      .attr("r", 15)
      .classed("hide", true)
      .classed("someClass", true);
    
    var circle2 = g.append("circle")
      .style("fill", "Green")
      .attr("cx", 250)
      .attr("cy", 90)
      .attr("r", 15)
      .classed("hide", true)
      .classed("someClass2", true);
    
    function mouseover(p) {
      var className = d3.select(this).attr("class");
      d3.selectAll("circle." + className).classed("hide", false);
    }
    
    function mouseout(p) {
      var className = d3.select(this).attr("class");
      d3.selectAll("circle." + className).classed("hide", true);
    }
    
    function click(p) {
      d3.select(this).on("mouseout", null);
      var className = d3.select(this).attr("class");
      d3.selectAll("circle." + className).classed("hide", false);
    }
    .hide {
      display: none;
    }
    
    text {
      cursor: pointer;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

    您还可以切换点击,使mouseout 再次工作:

    if(d3.select(this)[0][0].__onmouseout){
        d3.select(this).on("mouseout", null);
    } else {
        d3.select(this).on("mouseout", mouseout);
    }
    

    这里是“切换”功能的小提琴:https://jsfiddle.net/gerardofurtado/4zb9gL9r/1/

    和 Stack sn-p 中相同的代码:

    var svg = d3.select("body")
      .append("svg")
      .attr("width", 600)
      .attr("height", 400);
    var g = svg.append("g");
    var text = g.append("text")
      .text("Click me")
      .style("fill", "Blue")
      .attr("x", 50)
      .attr("y", 50)
      .classed("someClass", true)
      .on("mouseover", mouseover)
      .on("mouseout", mouseout)
      .on("click", click);
    
    var text2 = g.append("text")
      .text("Click me")
      .style("fill", "Blue")
      .attr("x", 50)
      .attr("y", 150)
      .classed("someClass2", true)
      .on("mouseover", mouseover)
      .on("mouseout", mouseout)
      .on("click", click);
    
    var circle = g.append("circle")
      .style("fill", "Orange")
      .attr("cx", 150)
      .attr("cy", 90)
      .attr("r", 15)
      .classed("hide", true)
      .classed("someClass", true);
    
    var circle2 = g.append("circle")
      .style("fill", "Green")
      .attr("cx", 250)
      .attr("cy", 90)
      .attr("r", 15)
      .classed("hide", true)
      .classed("someClass2", true);
    
    function mouseover(p) {
      var className = d3.select(this).attr("class");
      d3.selectAll("circle." + className).classed("hide", false);
    }
    
    function mouseout(p) {
      var className = d3.select(this).attr("class");
      d3.selectAll("circle." + className).classed("hide", true);
    }
    
    function click(p) {
      if (d3.select(this)[0][0].__onmouseout) {
        d3.select(this).on("mouseout", null);
      } else {
        d3.select(this).on("mouseout", mouseout);
      }
      var className = d3.select(this).attr("class");
      d3.selectAll("circle." + className).classed("hide", false);
    }
    .hide {
      display: none;
    }
    
    text {
      cursor: pointer;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

    【讨论】:

      猜你喜欢
      • 2014-06-10
      • 2010-09-15
      • 1970-01-01
      • 2021-08-01
      • 1970-01-01
      • 2014-08-30
      • 1970-01-01
      • 2018-03-26
      • 1970-01-01
      相关资源
      最近更新 更多