J'ai du mal à ajouter une légende de graphique à mon graphique d3js. Voici mon approche actuelle:
var legend = svg.append("g")
.attr("class", "legend")
.attr("x", w - 65)
.attr("y", 25)
.attr("height", 100)
.attr("width", 100);
legend.append("rect")
.attr("x", w - 65)
.attr("y", 25)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) { return color_hash[dataset.indexOf(d)][1] });
legend.append("text")
.attr("x", w - 65)
.attr("y", 25)
.text(function(d) { return color_hash[dataset.indexOf(d)][0] + ": " + d; });
Ensuite, j'essaie de styliser le .legend
classe:
.legend {
padding: 5px;
font: 10px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
Mais je n'ai pas beaucoup de chance.
Quelqu'un sait-il comment ajouter des légendes aux graphiques pour fournir la meilleure façon de le faire? Je ne trouve pas beaucoup de ressources pour cela en ligne.
Voici mon graphique entier: http://jsbin.com/ewiwag/2/edit
Vous devez lier des données aux nœuds (rectangles et éléments de texte) qui composent la légende.
Actuellement, vous obtenez une erreur lorsque vous essayez de styliser des rectangles:
Uncaught TypeError: Cannot read property '1' of undefined
La raison: il n'y a pas de données liées
legend.append("rect")
/*...*/
.style("fill", function(d) {
// d <---- is undefined
return color_hash[dataset.indexOf(d)][1]
});
Notez que D3 se concentre sur la transformation des données et opère sur les sélections. Donc, sélectionnez d'abord un ensemble de nœuds, puis liez les données
legend.selectAll('rect')
.data(dataset)
.enter()
Une fois que vous avez entré la sélection avec enter
, vous pouvez ajouter des nœuds et appliquer des propriétés dynamiquement. Notez que pour éviter de créer des rectangles au-dessus des autres, lorsque vous définissez la propriété y
, passez le compteur i
et multipliez-le par un entier.
/*.....*/
.append("rect")
.attr("x", w - 65)
.attr("y", function(d, i){ return i * 20;})
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d) {
var color = color_hash[dataset.indexOf(d)][1];
return color;
});
Voici l'exemple fixe: http://jsbin.com/ubafur/
Ok, voici une façon de le faire: http://jsbin.com/isuris/1/edit
Désolé, j'ai dû faire trop de changements pour pouvoir tout expliquer. Voyez si vous pouvez le découvrir. Si vous avez des questions, posez-les dans les commentaires et je modifierai la réponse.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript" src="http://mbostock.github.com/d3/d3.js"></script>
<style type="text/css">
.axis path,
.axis line {
fill: none;
stroke: black;
shape-rendering: crispEdges;
}
.axis text {
font-family: sans-serif;
font-size: 11px;
}
.y1 {
fill: white;
stroke: orange;
stroke-width: 1.5px;
}
.y2 {
fill: white;
stroke: red;
stroke-width: 1.5px;
}
.y3 {
fill: white;
stroke: steelblue;
stroke-width: 1.5px;
}
.line {
fill: none;
stroke-width: 1.5px;
}
div.tooltip {
position: absolute;
text-align: center;
width: 50px;
height: 10px;
padding: 5px;
font: 10px sans-serif;
background: whiteSmoke;
border: solid 1px #aaa;
pointer-events: none;
box-shadow: 2px 2px 1px #888;
}
.legend {
padding: 5px;
font: 10px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.title {
font: 13px sans-serif;
}
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
var padding = 50;
var now = d3.time.hour.utc(new Date);
var dataset = [ [ ],[ ] ];
dataset[0].Push({x: d3.time.hour.utc.offset(now, -5), y: 0});
dataset[0].Push({x: d3.time.hour.utc.offset(now, -4), y: 0});
dataset[0].Push({x: d3.time.hour.utc.offset(now, -3), y: 2});
dataset[0].Push({x: d3.time.hour.utc.offset(now, -2), y: 0});
dataset[0].Push({x: d3.time.hour.utc.offset(now, -1), y: 0});
dataset[0].Push({x: now, y: 0});
dataset[1].Push({x: d3.time.hour.utc.offset(now, -5), y: 3});
dataset[1].Push({x: d3.time.hour.utc.offset(now, -4), y: 1});
dataset[1].Push({x: d3.time.hour.utc.offset(now, -3), y: 3});
dataset[1].Push({x: d3.time.hour.utc.offset(now, -2), y: 1});
dataset[1].Push({x: d3.time.hour.utc.offset(now, -1), y: 5});
dataset[1].Push({x: now, y: 1});
var color_hash = { 0 : ["Apple", "green"],
1 : ["mango", "orange"],
2 : ["cherry", "red"]
}
// Define axis ranges & scales
var yExtents = d3.extent(d3.merge(dataset), function (d) { return d.y; });
var xExtents = d3.extent(d3.merge(dataset), function (d) { return d.x; });
var xScale = d3.time.scale()
.domain([xExtents[0], xExtents[1]])
.range([padding, w - padding * 2]);
var yScale = d3.scale.linear()
.domain([0, yExtents[1]])
.range([h - padding, padding]);
// Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
// Define lines
var line = d3.svg.line()
.x(function(d) { return x(d.x); })
.y(function(d) { return y(d.y1, d.y2, d.y3); });
var pathContainers = svg.selectAll('g.line')
.data(dataset);
pathContainers.enter().append('g')
.attr('class', 'line')
.attr("style", function(d) {
return "stroke: " + color_hash[dataset.indexOf(d)][1];
});
pathContainers.selectAll('path')
.data(function (d) { return [d]; }) // continues the data from the pathContainer
.enter().append('path')
.attr('d', d3.svg.line()
.x(function (d) { return xScale(d.x); })
.y(function (d) { return yScale(d.y); })
);
// add circles
pathContainers.selectAll('circle')
.data(function (d) { return d; })
.enter().append('circle')
.attr('cx', function (d) { return xScale(d.x); })
.attr('cy', function (d) { return yScale(d.y); })
.attr('r', 3);
//Define X axis
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(5);
//Define Y axis
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//Add X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
.call(xAxis);
//Add Y axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
// Add title
svg.append("svg:text")
.attr("class", "title")
.attr("x", 20)
.attr("y", 20)
.text("Fruit Sold Per Hour");
// add legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("x", w - 65)
.attr("y", 25)
.attr("height", 100)
.attr("width", 100);
legend.selectAll('g').data(dataset)
.enter()
.append('g')
.each(function(d, i) {
var g = d3.select(this);
g.append("rect")
.attr("x", w - 65)
.attr("y", i*25)
.attr("width", 10)
.attr("height", 10)
.style("fill", color_hash[String(i)][1]);
g.append("text")
.attr("x", w - 50)
.attr("y", i * 25 + 8)
.attr("height",30)
.attr("width",100)
.style("fill", color_hash[String(i)][1])
.text(color_hash[String(i)][0]);
});
</script>
</body>
</html>