web-dev-qa-db-ja.com

d3.js-マウスオーバーイベントがsvgグループで正しく機能しない

マウスカーソルがこのグラフ内にあるすべての場所に参照線が必要なグラフがあります。そして、この基準線は、グラフ内のマウスの動きに従います。

しかし、これはうまく機能しないようです。軸と軸の目盛り(.axisライン)でのみ機能します。デバッグ時に、マウスイベントがSVGに適用されてもグループではなく正常に機能することがわかりました。なぜですか?

ここに私のコードがあります:

test.html

<html>
<head>
<script src="jquery.js">
</script>
<script src="d3.v2.js">
</script>
<script src="retest.js">
</script>
<style type="text/css">
  .g_main {
    cursor:pointer;
  }

  .axis path, .axis line {
    stroke: #DBDBDB;
    /*shape-rendering: crispEdges;
    */
  }

  .y g:first-child text {
    display:none;
  }

  .y g:first-child line {
    stroke: #989898  ;
    stroke-width: 2.5px;
  }

  /*.x g:first-child line {
  stroke: black  ;
  stroke-width: 2.5px;
}
  */

  .y path {
    stroke: #989898  ;
    stroke-width: 2.5px;
  }

</style>
</head>
<body>  
<center>
  <button id="reload" onclick="loadViz();">
    load Graph
  </button>
  <div id="viz" class="viz">
  </div>    
</center>
<script>
  loadViz();
</script>
</body>
</html>

retest.js

var series,
classifications,
minVal,
maxVal,

svgW = 600,
svgH = 600,
//w = 1200,
//h = 1200,

vizPadding = {
    top: 120,
    right: 30,
    bottom: 120,
    left: 50
},

yAxMin_PA = 0,
yAxMax_PA = 50,
xAxMin_PA = 2002,
xAxMax_PA = 2008,
areaStrokeColors = ['#FF6600', '#3366FF', '#B8860B', '#458B00', 'white'];

var loadViz = function () {

    color = d3.scale.category10();

    data = {
        "lines": [{
                "line": [{
                        "X": 2002,
                        "Y": 42
                    }, {
                        "X": 2003,
                        "Y": 45
                    },

                    {
                        "X": 2005,
                        "Y": 47
                    },

                    {
                        "X": 2007,
                        "Y": 41
                    }
                ]
            }, {
                "line": [{
                        "X": 2003,
                        "Y": 33
                    }, {
                        "X": 2005,
                        "Y": 38
                    }, {
                        "Y": 36,
                        "X": 2008
                    }
                ]
            }, {

                "line": [{
                        "X": 2004,
                        "Y": 13
                    }, {
                        "X": 2005,
                        "Y": 19
                    }, {
                        "X": 2008,
                        "Y": 21
                    }
                ]
            }, {

                "line": [{
                        "X": 2003,
                        "Y": 20
                    }, {
                        "X": 2005,
                        "Y": 27
                    }, {
                        "X": 2008,
                        "Y": 29
                    }
                ]
            }
        ]
    };


    $("#viz").html("");
    buildBase();
    //setScales();
};

var buildBase = function () {

    margin = {
        top: 80,
        right: 120,
        bottom: 40,
        left: 40
    },
    width = 960 - margin.left - margin.right,
    height = 550 - margin.top - margin.bottom;

    t2 = height + margin.top + margin.bottom;

    x = d3.scale.linear()
        .domain([xAxMin_PA, xAxMax_PA])
        .range([0, width]);

    y = d3.scale.linear()
        .domain([yAxMin_PA, yAxMax_PA])
        .range([height, 0]);

    tickSizeToApplyX = 5;

    tickSizeToApplyY = 10;

    // Function to draw X-axis
    xAxis = d3.svg.axis()
        .scale(x)
        .ticks(tickSizeToApplyX)
        .tickSize(-height, 0, 0)
    //.tickSize(10)
    .orient("bottom")
        .tickPadding(5);

    // Function to draw Y-axis
    yAxis = d3.svg.axis()
        .scale(y)
        .ticks(tickSizeToApplyY)
        .tickSize(-width, 0, 0)
    //.tickSize(0)
    .orient("left")
        .tickPadding(5);

    // Define the line
    var valueline = d3.svg.line()
        .x(function (d) { /*console.log(d.X);*/
            return x(d.X);
        })
        .y(function (d) { /*console.log(d.Y);*/
            return y(d.Y);
        });

    // Define the line
    var referline = d3.svg.line()
        .x(function (dx) { /*console.log(d.X);*/
            return dx;
        })
        .y(function (dy) { /*console.log(d.Y);*/
            return dy;
        });

    // Append SVG into the html
    var viz = d3.select("#viz")
        .append("svg")
        .attr("width", width + margin.left + margin.right + 10)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("class", "g_main")
        .attr("transform", "translate(" + margin.left + "," + ((margin.top) - 30) + ")");

    viz.on("mousemove", function () {
        cx = d3.mouse(this)[0];
        cy = d3.mouse(this)[1];
        console.log("xx=>" + cx + "yy=>" + cy);
        redrawline(cx, cy);
    })
        .on("mouseover", function () {
            d3.selectAll('.line_over').style("display", "block");
        })
        .on("mouseout", function () {
            d3.selectAll('.line_over').style("display", "none");
        });

    //console.log(this);
    viz.append("line")
    //d3.select("svg").append("line")
    .attr("class", 'line_over')
        .attr("x1", 0)
        .attr("y1", 0)
        .attr("x2", x(xAxMax_PA))
        .attr("y2", 0)
        .style("stroke", "gray")
        .attr("stroke-dasharray", ("5,5"))
        .style("stroke-width", "1.5")
        .style("display", "none");

    // Draw X-axis
    viz.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

    // Draw Y-axis
    viz.append("g")
        .attr("class", function (d, i) {
            return "y axis"
        })
        .call(yAxis);


    function redrawline(cx, cy) {
        d3.selectAll('.line_over')
            .attr("x1", 0)
            .attr("y1", cy)
            .attr("x2", x(xAxMax_PA))
            .attr("y2", cy)
            .style("display", "block");
    }
};
24
user2339182

g要素は、クリックイベントをキャプチャできない単なる空のコンテナです( documentation for pointer-eventsプロパティ 詳細)。

ただし、マウスイベントはそれにバブルします。したがって、最初にgがすべてのポインターイベントを受け取ることを確認することで、目的の効果を実現できます。

.g_main {
  // ..
  pointer-events: all;
}

そして、マウスオーバーする場所として目に見えない長方形を追加します:

viz.on("mousemove", function () {
        cx = d3.mouse(this)[0];
        cy = d3.mouse(this)[1];
        redrawline(cx, cy);
    })
    .on("mouseover", function () {
        d3.selectAll('.line_over').style("display", "block");
    })
    .on("mouseout", function () {
        d3.selectAll('.line_over').style("display", "none");
    })
  .append('rect')
  .attr('class', 'click-capture')
  .style('visibility', 'hidden')
  .attr('x', 0)
  .attr('y', 0)
  .attr('width', width)
  .attr('height', height);

作業例: http://jsfiddle.net/H3W3k/

svg要素に適用したときに機能する理由について( docsから ):

「svg」要素はグラフィック要素ではなく、適合SVGスタンドアロンファイルでは、ルート要素の「svg」要素がポインターイベントのターゲットになることはありませんが、イベントはこの要素にバブルする可能性があります。ポインタイベントがグラフィック要素でヒットテストを肯定しない場合、SVGドキュメントフラグメントのズームとパンを許可するためのコンテキストメニューまたはコントロールの表示など、ユーザーエージェント固有のウィンドウ動作を呼び出す必要があります。 。

62
musically_ut