2015-12-10 6 views
5

Nel mio grafico a linee D3, sto cercando di creare un effetto di mouseover come in questo esempio: http://bl.ocks.org/mbostock/3902569D3: Ottenere valore più vicino dall'asse ordinale al passaggio del mouse

In questo esempio l'autore utilizza la funzione bisettrice, che è , per quanto ho capito, supportato solo per scale lineari. Il problema è che nel mio grafico ho un asse x ordinale con diverse tuple punto di intervallo discrete. Quindi, se è come nella situazione seguente (m = posizione del mouse), voglio ottenere la posizione in pixel del valore x più vicino che sarebbe x2 in questo esempio.

  m 
     | 
x1----------x2----------x3 

C'è un modo per farlo?

+2

Si potrebbe prendere tutti i valori nel dominio della scala ordinale, tr ingrandirli al loro valore di uscita e vedere quale è il più vicino. –

risposta

6

Usando il tuo esempio collegato, ecco una rapida implementazione della funzione mousemove per una scala ordinale:

var tickPos = x.range(); 
function mousemove(d){ 
    var m = d3.mouse(this), 
     lowDiff = 1e99, 
     xI = null; 
    // if you have a large number of ticks 
    // this search could be optimized 
    for (var i = 0; i < tickPos.length; i++){ 
    var diff = Math.abs(m[0] - tickPos[i]); 
    if (diff < lowDiff){ 
     lowDiff = diff; 
     xI = i; 
    } 
    } 
    focus 
    .select('text') 
    .text(ticks[xI]); 
    focus 
    .attr("transform","translate(" + tickPos[xI] + "," + y(data[xI].y) + ")"); 
} 

codice completo:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 
<style> 
 
    body { 
 
    font: 10px sans-serif; 
 
    } 
 
    
 
    .axis path, 
 
    .axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
    } 
 
    
 
    .line { 
 
    fill: none; 
 
    stroke: steelblue; 
 
    stroke-width: 1.5px; 
 
    } 
 
    
 
    .overlay { 
 
    fill: none; 
 
    pointer-events: all; 
 
    } 
 
    
 
    .focus circle { 
 
    fill: none; 
 
    stroke: steelblue; 
 
    } 
 
</style> 
 

 
<body> 
 
    <script src="//d3js.org/d3.v3.min.js"></script> 
 
    <script> 
 
    var margin = { 
 
     top: 20, 
 
     right: 20, 
 
     bottom: 30, 
 
     left: 50 
 
     }, 
 
     width = 960 - margin.left - margin.right, 
 
     height = 500 - margin.top - margin.bottom; 
 

 

 
    var x = d3.scale.ordinal() 
 
     .rangeRoundPoints([0, width]); 
 

 
    var y = d3.scale.linear() 
 
     .range([height, 0]); 
 

 
    var xAxis = d3.svg.axis() 
 
     .scale(x) 
 
     .orient("bottom"); 
 

 
    var yAxis = d3.svg.axis() 
 
     .scale(y) 
 
     .orient("left"); 
 

 
    var line = d3.svg.line() 
 
     .x(function(d) { 
 
     return x(d.x); 
 
     }) 
 
     .y(function(d) { 
 
     return y(d.y); 
 
     }); 
 

 
    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 = [{ 
 
     x: 'A', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'B', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'C', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'D', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'E', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'F', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'G', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'H', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'I', 
 
     y: Math.random() * 10 
 
    }, { 
 
     x: 'J', 
 
     y: Math.random() * 10 
 
    }]; 
 

 
    var ticks = data.map(function(d) { 
 
     return d.x 
 
    }); 
 
    x.domain(ticks); 
 
    y.domain(d3.extent(data, function(d) { 
 
     return d.y; 
 
    })); 
 

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

 
    svg.append("path") 
 
     .datum(data) 
 
     .attr("class", "line") 
 
     .attr("d", line); 
 

 
    var focus = svg.append("g") 
 
     .attr("class", "focus") 
 
     .style("display", "none"); 
 

 
    focus.append("circle") 
 
     .attr("r", 4.5); 
 

 
    focus.append("text") 
 
     .attr("x", 9) 
 
     .attr("dy", ".35em") 
 
     .style('') 
 

 
    svg.append("rect") 
 
     .attr("class", "overlay") 
 
     .attr("width", width) 
 
     .attr("height", height) 
 
     .on("mouseover", function() { 
 
     focus.style("display", null); 
 
     }) 
 
     .on("mouseout", function() { 
 
     focus.style("display", "none"); 
 
     }) 
 
     .on("mousemove", mousemove); 
 
    
 
    var tickPos = x.range(); 
 
    function mousemove(d){ 
 
     var m = d3.mouse(this), 
 
      lowDiff = 1e99, 
 
      xI = null; 
 
     for (var i = 0; i < tickPos.length; i++){ 
 
     var diff = Math.abs(m[0] - tickPos[i]); 
 
     if (diff < lowDiff){ 
 
      lowDiff = diff; 
 
      xI = i; 
 
     } 
 
     } 
 
     focus 
 
     .select('text') 
 
     .text(ticks[xI]); 
 
     focus 
 
     .attr("transform","translate(" + tickPos[xI] + "," + y(data[xI].y) + ")"); 
 
    } 
 
    </script>

Problemi correlati