Ajout d'une légende dans D3
j'ai de la difficulté à ajouter une légende de carte à ma carte 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; });
Alors j'essaie de style .legend
catégorie:
.legend {
padding: 5px;
font: 10px sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
mais je n'ai pas beaucoup de chance.
est-ce que quelqu'un est familier avec l'ajout de légendes aux cartes? Je ne trouve pas beaucoup de ressources pour cela en ligne.
Voici mon graphique: http://jsbin.com/ewiwag/2/edit
2 réponses
vous devez lier les données aux noeuds (rectangles et éléments de texte) qui composent la légende.
Actuellement vous obtenez une erreur en essayant de style rectangles:
Uncaught TypeError: Cannot read property '1' of undefined
La raison: il n'y a pas de données lié
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. Ainsi, tout d'abord sélectionner un ensemble de noeuds et ensuite lier les données
legend.selectAll('rect')
.data(dataset)
.enter()
une fois que vous entrez la sélection avec enter
, vous pouvez ajouter des noeuds et appliquer propriétés de façon dynamique. Notez que pour éviter de créer des rectangles au-dessus des autres, lors de la définition du y
propriété passez le i
compteur et le multiplier 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/3
Ok, voici une façon de le faire: http://jsbin.com/isuris/1/edit
Désolé, j'avais à faire trop de changements pour être en mesure de l'expliquer. Voyez si vous pouvez le comprendre. 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>