2013-03-22 16 views
33

Ok, sto iniziando a familiarizzare un po 'con D3, ma sono ancora un po' confuso su alcune cose. Ora sto provando a disegnare le linee della griglia, ma mi sto rendendo conto che potrei star tagliando o farlo correttamente. Ho provato ad aggiungere alcune linee della griglia, usando un tutorial, ma ho finito con un sacco di codice che mi sembra di essere jimmy rigging al fine di farlo allineare correttamente. Mi chiedevo se qualcuno potesse indicarmi un modo migliore di scrivere questo ...Modo corretto per tracciare linee di griglia

Il codice originale è questo.

 <script type="text/javascript"> 

      //Width and height 
      var w = 800; 
      var h = 400; 
      var padding = 20; 
      var border=1; 
      var bordercolor='black'; 


      var dataset = [ 
          [5, 20], [480, 90], [250, 50], [100, 33], [330, 95],[-50,-100],[50,-45], 
          [410, 12], [475, 44], [25, 67], [85, 21], [220, 88],[-480, -467], [3,-90],[468,481] 
          ]; 

       // create scale functions 
       var xScale = d3.scale.linear() 
           .domain([d3.min(dataset, function(d) { return d[0]; }), d3.max(dataset, function(d) { return d[0]; })]) 
           .range([padding, w - padding * 2]); 

      var yScale = d3.scale.linear() 
           .domain([d3.min(dataset, function(d) { return d[0]; }), d3.max(dataset, function(d) { return d[1]; })]) 
           .range([h - padding, padding]); 

       var rScale = d3.scale.linear() 
       .domain( [-100,  d3.max(dataset, function(d) { return d[1];   })] ) 
       .range([2,5]); 

      //Create SVG element 
      var svg = d3.select("body") 
         .append("svg") 
         .attr("width", w) 
         .attr("height", h) 
         .attr("border",border) 
         ; 

      //define X axis this is rly a function, remember, variables can hold functions in JS 
       var xAxis = d3.svg.axis() 
         .scale(xScale) 
         .orient("bottom") 
         .ticks(1) 
         .tickSize(-h, 0, 0) 
         ; //Set rough # of ticks 


      //Define Y axis 
       var yAxis = d3.svg.axis() 
         .scale(yScale) 
         .orient("left") 
         .ticks(1) 
         .tickSize(-w, 0, 0) 
         ; 




       //create the circles 
      svg.selectAll("circle") 
       .data(dataset) 
       .enter() 
       .append("circle") 
       .attr("cx", function(d) { 
        return xScale(d[0]); 
       }) 
       .attr("cy", function(d) { 
        return yScale(d[1]); 
       }) 
       .attr("r", 3); 





    // draw axes here 
    svg.append("g") 
    .attr("class", "axis") //assign "axis" class 
    .attr("transform", "translate(0," + (h - padding) +")") 
    .call(xAxis); 



     svg.append("g") 
    .attr("class", "axis") //assign "axis" class 
    .attr("transform", "translate(" + padding + ",0)"  ) 
    .call(yAxis); 
// end draw axes here 
     </script> 

e il codice ho aggiunto nel secondo collegamento è qui

var vis = svg.append("svg:g") 
    .attr("transform", "translate(20,0)") 


var rules = vis.append("svg:g").classed("rules", true) 


rules.append("svg:g").classed("grid x_grid", true) 
    .attr("transform", "translate(-20,"+h+")") 
    .call(d3.svg.axis() 
     .scale(xScale) 
     .orient("bottom") 
     .ticks(4) 
     .tickSize(-h,0,0) 
     .tickFormat("") 
    ) 

rules.append("svg:g").classed("grid y_grid", true) 
    .call(d3.svg.axis() 
     .scale(yScale) 
     .orient("left") 
     .ticks(5) 
     .tickSize(-w,0,0) 
     .tickFormat("") 
    ) 

rules.append("svg:g").classed("labels x_labels", true) 
    .attr("transform", "translate(-20,"+ h +")") 
    .call(d3.svg.axis() 
     .scale(xScale) 
     .orient("bottom") 
     .ticks(4) 
     .tickSize(0) 
      .tickFormat("") 
     // .tickFormat(d3.time.format("%Y/%m")) 
    ) 

rules.append("svg:g").classed("labels y_labels", true) 
    .call(d3.svg.axis() 
     .scale(yScale) 
     .orient("left") 
     .ticks(5) 
     .tickSubdivide(1) 
     .tickSize(0, 0, 0) 
      .tickFormat("") 
    ) 

Anche in questo caso, davvero apprezzare alcun aiuto

risposta

11

è possibile utilizzare la funzione ticks() della bilancia per ottenere i valori di tic e quindi usali in una chiamata dati per tracciare le linee.

var ticks = xScale.ticks(4); 
rules.selectAll("path.xgrid").data(ticks).enter() 
    .append("path") 
    .attr("d", function(d) { 
     return "M" + xScale(d) + " " + padding + "L" + xScale(d) + " " + (h-padding); 
    }); 

È preferibile utilizzare un generatore di linee per le linee della griglia anziché creare manualmente il percorso. Funziona in modo simile per le linee della griglia, solo che la coordinata y è costante e varia da 0 a larghezza del grafico. Potrebbe essere necessario regolare i valori di inizio e fine per renderlo "bello".

+1

Sono d'accordo con Lars e ho trovato utile usare anche le zecche per le griglie. Vedi qui per una variante http://www.d3noob.org/2013/01/adding-grid-lines-to-d3js-graph.html – d3noob

+0

Questo era il link che ho usato per creare questa versione del mio grafico: http://goo.gl/OmX52 ma alla fine ho dovuto fare un pasticcio manuale con la "trasformazione" per far coincidere le righe e non era ancora perfettamente in linea. Lars, ho copiato il tuo codice nel mio

61

Supponendo che sia stato definito lo standard Mike Bostock'smargins e che sia stata definita una scala lineare per l'asse y, il codice seguente creerà linee di griglia orizzontali senza utilizzare tickSize().

svg.selectAll("line.horizontalGrid").data(yScale.ticks(4)).enter() 
    .append("line") 
     .attr(
     { 
      "class":"horizontalGrid", 
      "x1" : margin.right, 
      "x2" : width, 
      "y1" : function(d){ return yScale(d);}, 
      "y2" : function(d){ return yScale(d);}, 
      "fill" : "none", 
      "shape-rendering" : "crispEdges", 
      "stroke" : "black", 
      "stroke-width" : "1px" 
     }); 
+5

Grazie! Non sapevo che possiamo dichiarare molti attr insieme – muyueh

+5

Assolutamente! Questo singolo oggetto attributo può anche essere usato con .style ({...}) – arete

+0

Ti dispiacerebbe spiegare la tua motivazione dietro non usare Ticksize e perché la tua soluzione potrebbe essere considerata una pratica migliore? – Seanny123

16

Vorrei suggerire di usare d3.svg.axis(). Scala() per legare la griglia per le coordinate. Ho disegnato un quick example in base al codice: http://jsfiddle.net/temirov/Rt65L/1/

Grid example

Il succo è quello di utilizzare l'esistente scale, X e Y, e di utilizzare le zecche come griglia. Poiché yAxis e xAxis sono già definiti, possiamo semplicemente riutilizzarli. Ecco il codice rilevante:

//Draw a grid 
var numberOfTicks = 6; 

var yAxisGrid = yAxis.ticks(numberOfTicks) 
    .tickSize(w, 0) 
    .tickFormat("") 
    .orient("right"); 

var xAxisGrid = xAxis.ticks(numberOfTicks) 
    .tickSize(-h, 0) 
    .tickFormat("") 
    .orient("top"); 

svg.append("g") 
    .classed('y', true) 
    .classed('grid', true) 
    .call(yAxisGrid); 

svg.append("g") 
    .classed('x', true) 
    .classed('grid', true) 
    .call(xAxisGrid); 
+3

+1 Questo è il modo migliore per farlo, poiché significa che se si modifica la proprietà .ticks() sul proprio asse , quindi si rifletterà nelle linee della griglia. – ninjaPixel

1

seguito @ idea di Arete, è possibile utilizzare il seguente per evitare di ri-disegno inutilmente la griglia:

function createsGrid(data) { 
     var grid = gridLine.selectAll("line.horizontalGrid").data(scaleY.ticks()); 

     grid.enter() 
     .append("line") 
     .attr("class","horizontalGrid"); 

     grid.exit().remove(); 

     grid.attr({ 
       "x1":0, 
       "x2": width, 
       "y1": function (d) { return scaleY(d); }, 
       "y2": function (d) { return scaleY(d); } 
       }); 
} 

e definire quanto segue nel file CSS

line.horizonalGrid{ 
    fill : none; 
shape-rendering : crispEdges; 
stroke : black; 
stroke-width : 1.5px; 
} 
0

Si potrebbe utilizzare innerTickSize, invece di tickSize:

  var xAxis = d3.svg.axis() 
        .scale(xScale) 
        .orient("bottom") 
        .ticks(1) 
        .innerTickSize(-h); 
1

Nel progetto d3fc abbiamo creato uno gridlines component che esegue il rendering esattamente allo stesso modo dell'asse D3 (v4).

Ecco un esempio di utilizzo:

var width = 500, height = 250; 
var container = d3.select("#gridlines") 
    .append("svg") 
    .attr("width", width) 
    .attr("height", height); 

var xScale = d3.scaleLinear() 
    .range([0, 100]); 

var yScale = d3.scaleLinear() 
    .range([0, 100]); 

var gridline = fc.annotationSvgGridline() 
    .xScale(xScale) 
    .yScale(yScale); 

container.append("g") 
    .call(gridline); 

che rende come segue:

enter image description here

La spaziatura delle griglie è determinata dalle zecche forniti dagli assi associati.

Disclosure: sono un collaboratore principale del progetto d3fc!

Problemi correlati