2016-09-07 2 views
0

Ich habe folgende Datenanzeige auf einem d3 Diagramm:d3 Snap Bürste Daten ein xAchse

[{ 
    "Date": "2012", 
    "Total": 5340 
}, { 
    "Date": "2013", 
    "Total": 4120 
}, { 
    "Date": "2014", 
    "Total": 1259 
}, { 
    "Date": "2015", 
    "Total": 3617 
}, { 
    "Date": "2016", 
    "Total": 2005 
}] 

Die Grafik hat auch eine Bürste auf sie, damit der Benutzer auf eine Auswahl von Jahren, indem Sie den Pinsel konzentrieren . Mit dem Pinsel kann der Benutzer jedoch zwischen dem ersten und dem letzten Jahr über alle Daten ziehen.

Was ich tun möchte, ist es zu machen, die Jahre zu knipsen, während der Benutzer bürstet. So ist https://bl.ocks.org/mbostock/6232620

die Idee, dass das Jahr abgerundet wird zuerst ab und dann wird das Ausmaß modifiziert, bevor angewendet:

Hier ist mein Code für die Bürsten Ereignisse:

var brush = d3.svg.brush() 
    .x(xScale2) 
    .on('brush', brushed); 

function brushed() { 
    var min = d3.min(data.map(function (d) { 
     return d.total; 
    })); 
    var max = d3.max(data.map(function (d) { 
     return d.total; 
    })); 
    var extent = brush.extent(); 
    if (!brush.empty()) { 

     // Snap to years 
      var newBrush = extent.map(d3.time.year.round); 
      if (newBrush[0] >= newBrush[1]) {// If empty when rounded, use floor & ceil instead. 
       newBrush[0] = d3.time.year.floor(extent[0]); 
       newBrush[1] = d3.time.year.ceil(extent[1]); 

      } 
      // update the extent 
      brush.extent([newBrush[0], newBrush[1]]); 
      extent = brush.extent(); 

      xScale.domain(brush.empty() ? xScale2.domain() : extent); 
      yScale.domain([ 
       d3.min(data.map(function (d) { 
        return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : max; 
       })), 
       d3.max(data.map(function (d) { 
        return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : min; 
       })) 
      ]); 

     xScale.domain(brush.empty() ? xScale2.domain() : extent); 
     yScale.domain([ 
      d3.min(data.map(function (d) { 
       return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : max; 
      })), 
      d3.max(data.map(function (d) { 
       return (d.date >= extent[0] && d.date <= extent[1]) ? d.total : min; 
      })) 
     ]); 
    } 
    totalChart.attr('d', totalLine); // update line 
    focus.select('.x.axis').call(xAxis); // update xAxis 
    focus.select('.y.axis').call(yAxis); // update yAxis 
} 

Diese auf basiert zu den Domains und sollte den Pinsel Snap machen ... aber es schnappt nicht ... stattdessen macht es den Benutzer kämpfen, es zwischen den Jahren zu ziehen. Ich möchte es auf das nächste Jahr, wenn der Benutzer beginnt zu ziehen. Sie sollten sich nie zwischen den Jahren hin- und herziehen können.

+0

Sie wollen es nur jährlich arbeiten, oder Sie wollen es Daten in Daten gerundet werden? – Mehraban

+0

@SaeedAdelMehraban Nur einmal in diesem Beispiel und dann, wenn es richtig einrastet, kann ich es an meine anderen Datumsformate anpassen. Kurz gesagt: Schnapp dir die Jahre. – Cameron

+0

Ich habe meine Antwort auf die Arbeit mit d3 v3 aktualisiert. – Mehraban

Antwort

2

Hier ist mobostock code mit Jahrfang. Es hat nur einen kleinen Fehler für Hintergrundgrenzen.

Dieser Code funktioniert gut, außer für einen kleinen Fehler im Hintergrund/Brush-Element-Sync.

var margin = {top: 0, right: 40, bottom: 50, left: 40}, 
 
    width = 500 - margin.left - margin.right, 
 
    height = 100 - margin.top - margin.bottom; 
 
var x = d3.time.scale() 
 
    .domain([new Date(2012, 1, 1), new Date(2023, 1, 1)]) 
 
    .range([0, width]); 
 
var brush = d3.svg.brush() 
 
    .x(x) 
 
    .extent([new Date(2014, 1, 1), new Date(2015, 1, 1)]) 
 
    .on("brushend", brushended); 
 
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 + ")"); 
 
svg.append("rect") 
 
    .attr("class", "grid-background") 
 
    .attr("width", width) 
 
    .attr("height", height); 
 
svg.append("g") 
 
    .attr("class", "x grid") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.svg.axis() 
 
     .scale(x) 
 
     .orient("bottom") 
 
     .ticks(d3.time.months, 6) 
 
     .tickSize(-height) 
 
     .tickFormat("")) 
 
    .selectAll(".tick") 
 
    .classed("minor", function(d) { return d.getHours(); }); 
 
svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(d3.svg.axis() 
 
     .scale(x) 
 
     .orient("bottom") 
 
     .ticks(d3.time.years) 
 
     .tickPadding(0)) 
 
    .selectAll("text") 
 
    .attr("x", 6) 
 
    .style("text-anchor", null); 
 
var gBrush = svg.append("g") 
 
    .attr("class", "brush") 
 
    .call(brush) 
 
    .call(brush.event); 
 
gBrush.selectAll("rect") 
 
    .attr("height", height); 
 
function brushended() { 
 
    if (!d3.event.sourceEvent) return; // only transition after input 
 
    var extent0 = brush.extent(), 
 
     extent1 = extent0.map(d3.time.year.round); 
 
    // if empty when rounded, use floor & ceil instead 
 
    if (extent1[0] >= extent1[1]) { 
 
    extent1[0] = d3.time.year.floor(extent0[0]); 
 
    extent1[1] = d3.time.year.ceil(extent0[1]); 
 
    } 
 
    d3.select(this).transition() 
 
     .call(brush.extent(extent1)) 
 
     .call(brush.event); 
 
}
.axis text { 
 
    font: 11px sans-serif; 
 
} 
 
.axis path { 
 
    display: none; 
 
} 
 
.axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
} 
 
.grid-background { 
 
    fill: #ddd; 
 
} 
 
.grid line, 
 
.grid path { 
 
    fill: none; 
 
    stroke: #fff; 
 
    shape-rendering: crispEdges; 
 
} 
 
.grid .minor.tick line { 
 
    stroke-opacity: .5; 
 
} 
 
.brush .extent { 
 
    stroke: #000; 
 
    fill-opacity: .125; 
 
    shape-rendering: crispEdges; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script> 
 

 
<body> 
 
</body>

+0

Ist Brush.move ein neues Feature in 4.0 von d3? – Cameron

+0

@Cameron Wie Sie d3 Version in diesem Beispielcode sehen können, ist v4. Sie können den Unterschied zwischen den Brushes v3 und v4 [hier] sehen (https://github.com/d3/d3-brush/blob/master/README.md) – Mehraban

+0

Was macht 'brush.move' das' brush.exxtent ?. 'nicht? Wie Sie in meinem Beispiel sehen können, aktualisiere ich die Werte in 'brush.extent', um zu versuchen, es zu fangen. Da ich d3.v3 benutze, das 'brush.move' nicht hat. Vielen Dank. – Cameron