我试图将图例放在堆积的条形图对齐块的下方。无法正确过渡。下面是我拥有的代码,此刻,图例出现在左上角,我要执行的操作是将其正确放置在堆积条下方的tranistion,是否有任何建议建议我如何进行转换以便适合svg也一样任何建议都会被采纳
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Example</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<style>
</style>
</head>
<style>
</style>
<body>
<div class="canvas">
</div>
<script>
var data = [
{month: "Q1-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q2-2016", apples: 1600, bananas: 1440, cherries: -960},
{month: "Q3-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q4-2016", apples: 320, bananas: 480, cherries: -640},
{month: "Q5-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q6-2016", apples: 1600, bananas: 1440, cherries: -960},
{month: "Q7-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q8-2016", apples: 320, bananas: 480, cherries: -640},
{month: "Q9-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q10-2016", apples: 1600, bananas: 1440, cherries: 960},
{month: "Q11-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q12-2016", apples: 320, bananas: 480, cherries: -640},
];
var series = d3.stack()
.keys(["apples", "bananas", "cherries"])
.offset(d3.stackOffsetDiverging)
(data);
var margin = {top: 20, right: 30, bottom: 30, left: 60},
width = 900,
height = 600,
padding = 40,
svg = d3.select(".canvas").append('svg').attr('height', height).attr('width',width);
var x = d3.scaleBand()
.domain(data.map(function(d){return d.month;}))
.rangeRound([margin.left, width-margin.right])
.padding(0.1);
var y = d3.scaleLinear()
.domain([d3.min(series, stackMin), d3.max(series, stackMax)])
.rangeRound([height - margin.bottom, margin.top]);
var colors = ["#66b3ff", "#b3d9ff", "#99ddff", "#99ffdd"];
var z = d3.scaleOrdinal(colors);
//create and call the axes
const xAxis = d3.axisBottom(x);
const yAxis = d3.axisLeft(y);
console.log(series);
svg.append('g')
.selectAll('g')
.data(series)
.enter().append('g')
.attr('fill', function (d) {
return z(d.key);
})
.selectAll('rect')
.data(function(d){ return d; })
.enter().append('rect')
.attr('width', x.bandwidth)
.attr('x', function(d){ return x(d.data.month)})
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
svg.append("g")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
svg.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y));
var legend = svg.append('g')
.attr('class', 'legend')
.attr('transform', 'translate(' + (padding + 12) + ',0)');
legend.selectAll('rect')
.data(series)
.enter()
.append('rect')
.attr('x', 0)
.attr('y', function(d,i){
return i * 18;
})
.attr('width', 12)
.attr('height', 12)
.attr('fill', function(d,i){
return z(i);
});
legend.selectAll('text')
.data(series)
.enter()
.append('text')
.text(function(d){
return d.key;
})
.attr('x', -18)
.attr('y', function(d, i){
return i * 18;
})
.attr('text-anchor', 'start')
.attr('alignment-baseline', 'hanging');
function stackMin(serie) {
return d3.min(serie, function(d) { return d[0]; });
}
function stackMax(serie) {
return d3.max(serie, function(d) { return d[1]; });
}
</script>
</body>
</html>
答案 0 :(得分:1)
您的代码中有些错误,所以我尝试修复其中的一些问题。
您的图表元素(即条形图和轴图)应添加到组中。这样可以根据需要适当地移动/翻译它。我创建一个chart
变量,并将这些元素分配给它,而不是直接分配给svg。这也使您在控制台中查看结构时也更容易看到。
图例区域的高度应在图表中声明和说明。我将其声明为变量legendh
,并在y轴范围内进行了说明。
如果您希望图例组出现在图表下方,则需要将其转换为图表下方。您之前提到的对.attr('transform', 'translate(' + (padding + 12) + ',0)');
组的变换使y坐标为0。我将其更改为.attr('transform', 'translate(' + (padding + 12) + ','+ (height - legendh) + ')');
。这告诉图例组从顶部向下移动height - legendh
数量,从而将其放置在图表下方。
最后,图例中的颜色与图表/条中的颜色不匹配。这是因为您的小节填充已由d.key
控制,但图例填充基于i
。我选择使其均匀并使用z(i)
获得颜色。
这是工作区:https://bl.ocks.org/akulmehta/80153b35ab7498d30408f92cfa50f356
这是工作代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>D3 Example</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<link href='https://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<style>
</style>
</head>
<style>
</style>
<body>
<div class="canvas">
</div>
<script>
var data = [
{month: "Q1-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q2-2016", apples: 1600, bananas: 1440, cherries: -960},
{month: "Q3-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q4-2016", apples: 320, bananas: 480, cherries: -640},
{month: "Q5-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q6-2016", apples: 1600, bananas: 1440, cherries: -960},
{month: "Q7-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q8-2016", apples: 320, bananas: 480, cherries: -640},
{month: "Q9-2016", apples: 3840, bananas: 1920, cherries: -1960},
{month: "Q10-2016", apples: 1600, bananas: 1440, cherries: 960},
{month: "Q11-2016", apples: 640, bananas: 960, cherries: -640},
{month: "Q12-2016", apples: 320, bananas: 480, cherries: -640},
];
var series = d3.stack()
.keys(["apples", "bananas", "cherries"])
.offset(d3.stackOffsetDiverging)
(data);
var margin = {top: 20, right: 30, bottom: 30, left: 60},
width = 900,
height = 500,
legendh = 100, //determines the height of the legend below the chart
padding = 40,
svg = d3.select(".canvas").append('svg').attr('height', height).attr('width',width);
var x = d3.scaleBand()
.domain(data.map(function(d){return d.month;}))
.rangeRound([margin.left, width-margin.right])
.padding(0.1);
var y = d3.scaleLinear()
.domain([d3.min(series, stackMin), d3.max(series, stackMax)])
.rangeRound([height - margin.bottom - legendh, margin.top]);
var colors = ["#66b3ff", "#b3d9ff", "#99ddff", "#99ffdd"];
var z = d3.scaleOrdinal(colors);
//create and call the axes
const xAxis = d3.axisBottom(x);
const yAxis = d3.axisLeft(y);
var chart = svg.append('g').attr('id','chart'); //make a chart group inside the svg
chart.append('g')
.selectAll('g')
.data(series)
.enter().append('g')
.attr('fill', function (d,i) { //because the legend is based on i this should also be based on i
return z(i);
})
.selectAll('rect')
.data(function(d){ return d; })
.enter().append('rect')
.attr('width', x.bandwidth)
.attr('x', function(d){ return x(d.data.month)})
.attr("y", function(d) { return y(d[1]); })
.attr("height", function(d) { return y(d[0]) - y(d[1]); })
chart.append("g")
.attr("transform", "translate(0," + y(0) + ")")
.call(d3.axisBottom(x));
chart.append("g")
.attr("transform", "translate(" + margin.left + ",0)")
.call(d3.axisLeft(y));
var legend = svg.append('g')
.attr('class', 'legend')
.attr('transform', 'translate(' + (padding + 12) + ','+ (height - legendh) + ')');
legend.selectAll('rect')
.data(series)
.enter()
.append('rect')
.attr('x', 0)
.attr('y', function(d,i){
return i * 18;
})
.attr('width', 12)
.attr('height', 12)
.attr('fill', function(d,i){
console.log(z(i));
return z(i);
});
legend.selectAll('text')
.data(series)
.enter()
.append('text')
.text(function(d){
return d.key;
})
.attr('x', 15)
.attr('y', function(d, i){
return i * 18;
})
.attr('text-anchor', 'start')
.attr('alignment-baseline', 'hanging');
function stackMin(serie) {
return d3.min(serie, function(d) { return d[0]; });
}
function stackMax(serie) {
return d3.max(serie, function(d) { return d[1]; });
}
</script>
</body>
</html>