web-dev-qa-db-fra.com

Façon appropriée de dessiner un quadrillage

D'accord, je commence à me familiariser un peu avec D3 mais je suis encore un peu flou sur certaines choses. J'essaie maintenant de tracer des lignes de grille mais je me rends compte que je peux être en train de pirater ou de le faire correctement. J'ai essayé d'ajouter quelques lignes de grille, en utilisant un tutoriel, mais j'ai fini avec beaucoup de code que je semble être un gréement jimmy afin de l'aligner correctement. Je me demandais si quelqu'un pouvait m'indiquer une meilleure façon d'écrire ceci ...

Voici le code d'origine.

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

et le code que j'ai ajouté dans le deuxième lien est ici

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

Encore une fois, appréciez vraiment toute aide

37
D3Chiq

En supposant que vous avez Mike Bostock's standard marges défini et que vous avez défini une échelle linéaire pour l'axe des y, le code suivant créera un quadrillage horizontal sans utiliser 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"
        });
67
arete

Je suggère d'utiliser d3.svg.axis (). Scale () pour attacher la grille à vos coordonnées. J'ai dessiné un exemple rapide basé sur votre code: http://jsfiddle.net/temirov/Rt65L/1/

Grid example

L'essentiel est d'utiliser les échelles existantes, x et y, et d'utiliser les graduations comme grille. Puisque yAxis et xAxis sont déjà définis, nous pouvons simplement les réutiliser. Voici le code pertinent:

//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);
18
Vadym Tyemirov

Vous pouvez utiliser la fonction ticks() de votre échelle pour obtenir les valeurs de graduation puis les utiliser dans un appel de données pour tracer les lignes.

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

Vous pouvez préférer utiliser un générateur de lignes pour les lignes de grille au lieu de créer le chemin manuellement. Cela fonctionne de manière similaire pour les lignes de la grille y, mais seulement que la coordonnée y est constante et s'étend de 0 à la largeur du graphique. Il se peut que vous deviez ajuster les valeurs de début et de fin pour lui donner un aspect "agréable".

11
Lars Kotthoff

Dans le projet d3fc, nous avons créé un composant quadrillage qui s'affiche exactement de la même manière que l'axe D3 (v4).

Voici un exemple d'utilisation:

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

Ce qui se traduit comme suit:

enter image description here

L'espacement des quadrillages est déterminé par les graduations fournies par les axes associés.

Divulgation: je suis l'un des principaux contributeurs au projet d3fc!

2
ColinE

Vous pouvez simplement utiliser innerTickSize, au lieu de tickSize:

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

Suivant l'idée de @ arete, vous pouvez utiliser ce qui suit pour éviter de redessiner inutilement le quadrillage:

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

et définissez les éléments suivants dans votre fichier CSS

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