javascript html d3.js

javascript - d3.js: el evento mouseover no funciona correctamente en el grupo svg



html (1)

Tengo un gráfico para el que necesito una línea de referencia en todas partes donde está el cursor del mouse dentro de este gráfico. Y esta línea de referencia seguirá los movimientos del ratón dentro del gráfico.

Pero esto no parece funcionar bien. Funciona solo en el eje y las marcas (líneas .axis) del eje. En la depuración, encontré que el evento del mouse funciona bien cuando se aplica sobre SVG pero no en el grupo, ¿por qué?

Aquí está mi código:

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"); } };


El elemento g es solo un contenedor vacío que no puede capturar eventos de clic (consulte la documentación para la propiedad de pointer-events de pointer-events para más detalles).

Sin embargo, los eventos del ratón hacen burbujas. Por lo tanto, el efecto que desea puede lograrse asegurándose primero de que la g reciba todos los eventos de puntero:

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

Y luego agregándole un rectángulo invisible como un lugar para pasar el ratón sobre:

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);

Ejemplo de trabajo: http://jsfiddle.net/H3W3k/

En cuanto a por qué funcionan cuando se aplican al elemento svg ( de los documentos ):

Tenga en cuenta que el elemento ''svg'' no es un elemento gráfico y, en un archivo autónomo SVG conforme, un elemento ''svg'' situado más a la raíz nunca será el objetivo de los eventos de puntero, aunque los eventos pueden propagarse a este elemento. Si un evento de puntero no da como resultado una prueba de impacto positiva en un elemento gráfico, debe evocar cualquier comportamiento de ventana específico del usuario-agente, como presentar un menú contextual o controles para permitir el zoom y la panorámica de un fragmento de documento SVG .