remove img hacer evento efecto con animate jquery d3.js

img - jquery class hover



Gráfico de líneas de multiseries con información sobre herramientas al pasar el mouse (1)

La pregunta a la que hizo referencia la respondí en abril. Desde entonces, he aprendido un poco más sobre SVG y d3 , así que dejaré que esto sirva como una actualización de esa respuesta.

Tenga en cuenta que tomé prestado un poco de código del excelente ejemplo de código de @ Duopixel here .

Aquí están los detalles comentados:

// append a g for all the mouse over nonsense var mouseG = svg.append("g") .attr("class", "mouse-over-effects"); // this is the vertical line mouseG.append("path") .attr("class", "mouse-line") .style("stroke", "black") .style("stroke-width", "1px") .style("opacity", "0"); // keep a reference to all our lines var lines = document.getElementsByClassName(''line''); // here''s a g for each circle and text on the line var mousePerLine = mouseG.selectAll(''.mouse-per-line'') .data(cities) .enter() .append("g") .attr("class", "mouse-per-line"); // the circle mousePerLine.append("circle") .attr("r", 7) .style("stroke", function(d) { return color(d.name); }) .style("fill", "none") .style("stroke-width", "1px") .style("opacity", "0"); // the text mousePerLine.append("text") .attr("transform", "translate(10,3)"); // rect to capture mouse movements mouseG.append(''svg:rect'') .attr(''width'', width) .attr(''height'', height) .attr(''fill'', ''none'') .attr(''pointer-events'', ''all'') .on(''mouseout'', function() { // on mouse out hide line, circles and text d3.select(".mouse-line") .style("opacity", "0"); d3.selectAll(".mouse-per-line circle") .style("opacity", "0"); d3.selectAll(".mouse-per-line text") .style("opacity", "0"); }) .on(''mouseover'', function() { // on mouse in show line, circles and text d3.select(".mouse-line") .style("opacity", "1"); d3.selectAll(".mouse-per-line circle") .style("opacity", "1"); d3.selectAll(".mouse-per-line text") .style("opacity", "1"); }) .on(''mousemove'', function() { // mouse moving over canvas var mouse = d3.mouse(this); // move the vertical line d3.select(".mouse-line") .attr("d", function() { var d = "M" + mouse[0] + "," + height; d += " " + mouse[0] + "," + 0; return d; }); // position the circle and text d3.selectAll(".mouse-per-line") .attr("transform", function(d, i) { console.log(width/mouse[0]) var xDate = x.invert(mouse[0]), bisect = d3.bisector(function(d) { return d.date; }).right; idx = bisect(d.values, xDate); // since we are use curve fitting we can''t relay on finding the points like I had done in my last answer // this conducts a search using some SVG path functions // to find the correct position on the line // from http://bl.ocks.org/duopixel/3824661 var beginning = 0, end = lines[i].getTotalLength(), target = null; while (true){ target = Math.floor((beginning + end) / 2); pos = lines[i].getPointAtLength(target); if ((target === end || target === beginning) && pos.x !== mouse[0]) { break; } if (pos.x > mouse[0]) end = target; else if (pos.x < mouse[0]) beginning = target; else break; //position found } // update the text with y value d3.select(this).select(''text'') .text(y.invert(pos.y).toFixed(2)); // return position return "translate(" + mouse[0] + "," + pos.y +")"; }); });

Código de trabajo completo:

<!DOCTYPE html> <html> <head> <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> <style> body { font: 10px sans-serif; } .axis path, .axis line { fill: none; stroke: #000; shape-rendering: crispEdges; } .x.axis path { display: none; } .line { fill: none; stroke: steelblue; stroke-width: 1.5px; } </style> </head> <body> <script> var myData = "date New York San Francisco Austin/n/ 20111001 63.4 62.7 72.2/n/ 20111002 58.0 59.9 67.7/n/ 20111003 53.3 59.1 69.4/n/ 20111004 55.7 58.8 68.0/n/ 20111005 64.2 58.7 72.4/n/ 20111006 58.8 57.0 77.0/n/ 20111007 57.9 56.7 82.3/n/ 20111008 61.8 56.8 78.9/n/ 20111009 69.3 56.7 68.8/n/ 20111010 71.2 60.1 68.7/n/ 20111011 68.7 61.1 70.3/n/ 20111012 61.8 61.5 75.3/n/ 20111013 63.0 64.3 76.6/n/ 20111014 66.9 67.1 66.6/n/ 20111015 61.7 64.6 68.0/n/ 20111016 61.8 61.6 70.6/n/ 20111017 62.8 61.1 71.1/n/ 20111018 60.8 59.2 70.0/n/ 20111019 62.1 58.9 61.6/n/ 20111020 65.1 57.2 57.4/n/ 20111021 55.6 56.4 64.3/n/ 20111022 54.4 60.7 72.4/n"; var margin = { top: 20, right: 80, bottom: 30, left: 50 }, width = 500 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var parseDate = d3.time.format("%Y%m%d").parse; var x = d3.time.scale() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var color = d3.scale.category10(); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var line = d3.svg.line() .interpolate("basis") .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.temperature); }); var svg = d3.select("body").append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var data = d3.tsv.parse(myData); color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; })); data.forEach(function(d) { d.date = parseDate(d.date); }); var cities = color.domain().map(function(name) { return { name: name, values: data.map(function(d) { return { date: d.date, temperature: +d[name] }; }) }; }); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }), d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); }) ]); var legend = svg.selectAll(''g'') .data(cities) .enter() .append(''g'') .attr(''class'', ''legend''); legend.append(''rect'') .attr(''x'', width - 20) .attr(''y'', function(d, i) { return i * 20; }) .attr(''width'', 10) .attr(''height'', 10) .style(''fill'', function(d) { return color(d.name); }); legend.append(''text'') .attr(''x'', width - 8) .attr(''y'', function(d, i) { return (i * 20) + 9; }) .text(function(d) { return d.name; }); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") .call(yAxis) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", ".71em") .style("text-anchor", "end") .text("Temperature (ºF)"); var city = svg.selectAll(".city") .data(cities) .enter().append("g") .attr("class", "city"); city.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return color(d.name); }); city.append("text") .datum(function(d) { return { name: d.name, value: d.values[d.values.length - 1] }; }) .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.temperature) + ")"; }) .attr("x", 3) .attr("dy", ".35em") .text(function(d) { return d.name; }); var mouseG = svg.append("g") .attr("class", "mouse-over-effects"); mouseG.append("path") // this is the black vertical line to follow mouse .attr("class", "mouse-line") .style("stroke", "black") .style("stroke-width", "1px") .style("opacity", "0"); var lines = document.getElementsByClassName(''line''); var mousePerLine = mouseG.selectAll(''.mouse-per-line'') .data(cities) .enter() .append("g") .attr("class", "mouse-per-line"); mousePerLine.append("circle") .attr("r", 7) .style("stroke", function(d) { return color(d.name); }) .style("fill", "none") .style("stroke-width", "1px") .style("opacity", "0"); mousePerLine.append("text") .attr("transform", "translate(10,3)"); mouseG.append(''svg:rect'') // append a rect to catch mouse movements on canvas .attr(''width'', width) // can''t catch mouse events on a g element .attr(''height'', height) .attr(''fill'', ''none'') .attr(''pointer-events'', ''all'') .on(''mouseout'', function() { // on mouse out hide line, circles and text d3.select(".mouse-line") .style("opacity", "0"); d3.selectAll(".mouse-per-line circle") .style("opacity", "0"); d3.selectAll(".mouse-per-line text") .style("opacity", "0"); }) .on(''mouseover'', function() { // on mouse in show line, circles and text d3.select(".mouse-line") .style("opacity", "1"); d3.selectAll(".mouse-per-line circle") .style("opacity", "1"); d3.selectAll(".mouse-per-line text") .style("opacity", "1"); }) .on(''mousemove'', function() { // mouse moving over canvas var mouse = d3.mouse(this); d3.select(".mouse-line") .attr("d", function() { var d = "M" + mouse[0] + "," + height; d += " " + mouse[0] + "," + 0; return d; }); d3.selectAll(".mouse-per-line") .attr("transform", function(d, i) { console.log(width/mouse[0]) var xDate = x.invert(mouse[0]), bisect = d3.bisector(function(d) { return d.date; }).right; idx = bisect(d.values, xDate); var beginning = 0, end = lines[i].getTotalLength(), target = null; while (true){ target = Math.floor((beginning + end) / 2); pos = lines[i].getPointAtLength(target); if ((target === end || target === beginning) && pos.x !== mouse[0]) { break; } if (pos.x > mouse[0]) end = target; else if (pos.x < mouse[0]) beginning = target; else break; //position found } d3.select(this).select(''text'') .text(y.invert(pos.y).toFixed(2)); return "translate(" + mouse[0] + "," + pos.y +")"; }); }); </script> </body> </html>

He creado un gráfico de líneas de varias series usando este ejemplo de código bl.ocks.org . He logrado recrearlo en JSFiddle .

Ahora, estoy tratando de agregar una información sobre herramientas de mouseover de valor x, que muestra la información sobre herramientas en cada línea cuando pasa el cursor sobre su posición vertical. Algo así, pero para varias líneas.

Encontré esta respuesta de StackOverflow (incluye un JSFiddle ), pero parece que no puedo hacer que funcione con mi gráfico de líneas multiserie.

svg.append("path") // this is the black vertical line to follow mouse .attr("class","mouseLine") .style("stroke","black") .style("stroke-width", "1px") .style("opacity", "0"); var mouseCircle = causation.append("g") // for each line, add group to hold text and circle .attr("class","mouseCircle"); mouseCircle.append("circle") // add a circle to follow along path .attr("r", 7) .style("stroke", function(d) { console.log(d); return color(d.key); }) .style("fill","none") .style("stroke-width", "1px"); mouseCircle.append("text") .attr("transform", "translate(10,3)"); // text to hold coordinates var bisect = d3.bisector(function(d) { return d.YEAR; }).right; // reusable bisect to find points before/after line svg.append(''svg:rect'') // append a rect to catch mouse movements on canvas .attr(''width'', width) // can''t catch mouse events on a g element .attr(''height'', height) .attr(''fill'', ''none'') .attr(''pointer-events'', ''all'') .on(''mouseout'', function(){ // on mouse out hide line, circles and text d3.select(".mouseLine") .style("opacity", "0"); d3.selectAll(".mouseCircle circle") .style("opacity", "0"); d3.selectAll(".mouseCircle text") .style("opacity", "0"); }) .on(''mouseover'', function(){ // on mouse in show line, circles and text d3.select(".mouseLine") .style("opacity", "1"); d3.selectAll(".mouseCircle circle") .style("opacity", "1"); d3.selectAll(".mouseCircle text") .style("opacity", "1"); }) .on(''mousemove'', function() { // mouse moving over canvas d3.select(".mouseLine") .attr("d", function(){ yRange = y.range(); // range of y axis var xCoor = d3.mouse(this)[0]; // mouse position in x var xDate = x.invert(xCoor); // date corresponding to mouse x d3.selectAll(''.mouseCircle'') // for each circle group .each(function(d,i){ var rightIdx = bisect(data[1].values, xDate); // find date in data that right off mouse var interSect = get_line_intersection(xCoor, // get the intersection of our vertical line and the data line yRange[0], xCoor, yRange[1], x(data[i].values[rightIdx-1].YEAR), y(data[i].values[rightIdx-1].VALUE), x(data[i].values[rightIdx].YEAR), y(data[i].values[rightIdx].VALUE)); d3.select(this) // move the circle to intersection .attr(''transform'', ''translate('' + interSect.x + '','' + interSect.y + '')''); d3.select(this.children[1]) // write coordinates out .text(xDate.toLocaleDateString() + "," + y.invert(interSect.y).toFixed(0)); }); return "M"+ xCoor +"," + yRange[0] + "L" + xCoor + "," + yRange[1]; // position vertical line }); }); // from here: https://stackoverflow.com/a/1968345/16363 function get_line_intersection(p0_x, p0_y, p1_x, p1_y, p2_x, p2_y, p3_x, p3_y) { var rV = {}; var s1_x, s1_y, s2_x, s2_y; s1_x = p1_x - p0_x; s1_y = p1_y - p0_y; s2_x = p3_x - p2_x; s2_y = p3_y - p2_y; var s, t; s = (-s1_y * (p0_x - p2_x) + s1_x * (p0_y - p2_y)) / (-s2_x * s1_y + s1_x * s2_y); t = ( s2_x * (p0_y - p2_y) - s2_y * (p0_x - p2_x)) / (-s2_x * s1_y + s1_x * s2_y); if (s >= 0 && s <= 1 && t >= 0 && t <= 1) { // Collision detected rV.x = p0_x + (t * s1_x); rV.y = p0_y + (t * s1_y); } return rV; }

Entonces, para decirlo simplemente, quiero combinar mi gráfico de líneas JSFiddle con esta JSFiddle . ¿Alguien sabe cómo hacer esto? ¿O hay una manera más fácil de crear una información sobre herramientas como esta? Cualquier ayuda es apreciada!