2013-03-22 3 views
33

Хорошо, я начинаю немного больше знаком с D3, но я все еще немного туман на некоторые вещи. Теперь я пытаюсь рисовать линии сетки, но понимаю, что я могу взломать и сделать это правильно. Я попытался добавить некоторые линии сетки, используя учебник, но в итоге получилось много кода, который, по-видимому, я использую jimmy, чтобы его правильно подобрать. Мне было интересно, может ли кто-нибудь указать мне лучший способ написать это ...Правильный способ рисования линий сетки

Оригинальный код - это.

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

и код, который я добавил второй ссылке здесь

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

Опять же, на самом деле признателен за любую помощь

ответ

11

Вы можете использовать ticks() функцию вашего масштаба, чтобы получить значения клеща и затем используйте их в вызове данных для рисования строк.

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

Вы можете использовать линейный генератор для линий сетки вместо создания пути вручную. Это работает аналогично для y линий сетки, только то, что координата y постоянна и колеблется от 0 до ширины графика. Вам может потребоваться настроить начальные и конечные значения, чтобы они выглядели «хорошо».

+1

Я согласен с Ларсом и нашел использование галочек для использования в сетчатых сетях. См. Здесь для варианта http://www.d3noob.org/2013/01/adding-grid-lines-to-d3js-graph.html – d3noob

+0

Это была ссылка, которую я использовал для создания этой версии моего графика: http://goo.gl/OmX52, но в итоге мне пришлось вручную «преобразовать», чтобы линии соответствовали, и это все еще не идеально соответствовало. Ларс, я скопировал ваш код в свой

61

Предполагая, что у вас установлен Mike Bostock's стандарт margins, и вы определили линейную шкалу для оси y, следующий код создаст горизонтальные линии сетки, не используя 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

Спасибо! Я не знал, что мы можем объявить много attr вместе. – muyueh

+5

Абсолютно! Этот единственный объект атрибута также можно использовать с .style ({...}) – arete

+0

Не могли бы вы объяснить свою мотивацию не использовать Ticksize и почему ваше решение можно считать лучшей практикой? – Seanny123

16

Я хотел бы предложить использовать d3.svg.axis(). Масштаб(), чтобы связать сетку с вашими координатами. Я нарисовал quick example на основе кода: http://jsfiddle.net/temirov/Rt65L/1/

Grid example

Суть заключается в использовании существующих шкал, х и у, а также использовать в качестве тиков сетки. Поскольку yAxis и xAxis уже определены, мы можем просто повторно их использовать. Вот соответствующий код:

//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 Это defo лучший способ сделать это, так как это означает, что если вы измените свойство .ticks() на своей оси , то это будет отражено в линиях сетки. – ninjaPixel

1

Следуя @ идее ребру, вы можете использовать следующее, чтобы избежать перерисовывая излишне на линии сетки:

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

и определить следующее в файле CSS

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

Вы могли бы просто использовать innerTickSize, вместо tickSize:

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

В проекте d3fc мы создали gridlines component, который отображает точно так же, как ось D3 (v4).

Вот пример использования:

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

, которая оказывает следующим образом:

enter image description here

Расстояние между линиями сетки определяется тиков, поставляемых соответствующих осей.

Раскрытие информации: Я являюсь основным источником проекта d3fc!

Смежные вопросы