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
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"
});
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/
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);
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".
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:
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!
Vous pouvez simplement utiliser innerTickSize, au lieu de tickSize:
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(1)
.innerTickSize(-h);
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;
}