2015-12-10 6 views
5

In meiner D3 Linie Chart, versuchen I morgens einen Mouseover-Effekt wie in diesem Beispiel zu erstellen: http://bl.ocks.org/mbostock/3902569D3: nächster Wert von Ordnungs Achse mit der Maus darüber

In diesem Beispiel ist der Autor die Halbierungs Funktion verwendet, das ist soweit ich es verstehe, nur für lineare Skalen unterstützt. Das Problem ist, dass ich in meinem Diagramm eine Ordinal x Achse mit verschiedenen, diskreten RangePoint Tupel habe. Wenn es also in der Situation unten (m = Mausposition) ist, möchte ich die Pixelposition des nächsten x-Werts erhalten, der in diesem Beispiel x2 wäre.

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

Gibt es eine Möglichkeit, das zu tun?

+2

Sie nehmen könnte alle Werte im Bereich der Ordinalskala, tr Setzen Sie sie auf ihren Ausgabewert und sehen Sie, welcher am nächsten ist. –

Antwort

6

verknüpften Beispiel verwenden, hier ist eine schnelle Umsetzung der mousemove Funktion für eine Ordinalskala:

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

Voll Code:

<!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>

Verwandte Themen