如何在d3.js中交换x和y轴 [英] How to swap x and y axis in d3.js
问题描述
I am new in d3.js . I Want to swap the axis in d3.js. How i can convert X-axis into the y-axis and the y-axis into the x-axis while working with this example
我希望条形图从下到上,而不是从左到右? 这是代码
I want bars chart from bottom to top instead of left to right ? Here is the code
<script>
var outerWidth = 960;
var outerHeight = 500;
var margin = { left: 100, top: 8, right: 30, bottom: 47 };
var barPadding = 0.2;
var xColumn = 'Sales';
var xColumnTooltip = 'Segment';
var yColumn = 'Sub-Category';
var colorColumn = 'Segment';
var layerColumn = colorColumn;
var hoveredColorValue;
var hoveredStrokeColor = 'black';
var innerWidth = outerWidth - margin.left - margin.right;
var innerHeight = outerHeight - margin.top - margin.bottom;
var svg = d3
.select('body')
.append('svg')
.attr('width', outerWidth)
.attr('height', outerHeight);
var g = svg
.append('g')
.attr('transform', 'translate(' + margin.left+ ',' + margin.top + ')');
// This is the layer where the bars are drawn.
var baseBarLayer = g.append('g');
// This layer contains a semi-transparent overlay that fades out the base bars.
var overlayRect = g
.append('g')
.append('rect')
.attr('width', innerWidth)
.attr('height', innerHeight)
.attr('fill', 'none')
.style('pointer-events', 'none');
// This contains the subset of bars rendered on top when you hover over the entries in the color legend.
var foregroundBarLayer = g.append('g');
var xAxisG = g
.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + innerHeight + ')');
var yAxisG = g.append('g').attr('class', 'y axis');
var colorLegendG = g
.append('g')
.attr('class', 'color-legend')
.attr('transform', 'translate(635, 0)');
var xScale = d3.scale.linear().range([0, innerWidth]);
var yScale = d3.scale.ordinal().rangeBands([innerHeight, 0], barPadding);
var colorScale = d3.scale.category10();
var tipNumberFormat = d3.format(',');
// Use a tip offset to ensure the tooltip is not rendered off-screen or over the y-axis labels.
var tip = d3
.tip()
.attr('class', 'd3-tip')
.offset([60, 0])
.html(function(d) {
return [
d[colorColumn],
' in ',
d[yColumn],
': ',
tipNumberFormat(d[xColumnTooltip]),
' item(s)'
].join('');
});
g.call(tip);
// Use a modified SI formatter that uses "B" for billions.
var siFormat = d3.format('s');
var customTickFormat = function(d) {
return siFormat(d).replace('G', 'B');
};
var xAxis = d3.svg
.axis()
.scale(xScale)
.orient('bottom')
.ticks(5)
.tickFormat(customTickFormat)
.outerTickSize(0);
var yAxis = d3.svg
.axis()
.scale(yScale)
.orient('left')
.outerTickSize(0);
var colorLegend = d3.legend
.color()
.scale(colorScale)
.shapePadding(6.24)
.shapeWidth(25)
.shapeHeight(25)
.labelOffset(10);
function render(data) {
var nested = d3
.nest()
.key(function(d) {
return d[layerColumn];
})
.entries(data);
var stack = d3.layout
.stack()
.y(function(d) {
return d[xColumn];
})
.values(function(d) {
return d.values;
});
var layers = stack(nested.reverse()).reverse();
xScale.domain([
0,
d3.max(layers, function(layer) {
return d3.max(layer.values, function(d) {
return d.y + d.y0;
});
})
]);
yScale.domain(
layers[0].values.map(function(d) {
return d[yColumn];
})
);
colorScale.domain(
layers.map(function(layer) {
return layer.key;
})
);
colorScale.range(['#69acc8','#4a4ed8','#5700a3']);
xAxisG.call(xAxis);
yAxisG.call(yAxis);
renderBars(baseBarLayer, layers);
if (hoveredColorValue) {
setOverlayTransparency(0.7);
renderBars(
foregroundBarLayer,
layers.filter(function(layer) {
return layer.key === hoveredColorValue;
})
);
} else {
setOverlayTransparency(0.0);
renderBars(foregroundBarLayer, []);
}
colorLegendG.call(colorLegend);
// Move the legend text down a bit.
colorLegendG.selectAll('text').attr('y', 3);
listenForHover(colorLegendG.selectAll('rect'), data);
listenForHover(colorLegendG.selectAll('text'), data);
}
function renderBars(g, layers) {
var layerGs = g.selectAll('.layer').data(layers);
layerGs
.enter()
.append('g')
.attr('class', 'layer');
layerGs.exit().remove();
layerGs.style('fill', function(d) {
return colorScale(d.key);
});
var bars = layerGs.selectAll('rect').data(function(d) {
return d.values;
});
bars
.enter()
.append('rect')
.on('mouseover', function(d) {
tip.show(d);
// Ensure the tooltip is printed in the same x position (so it is not rendered off-screen to the left).
d3.select('.d3-tip').style('left', '200px');
})
.on('mouseout', tip.hide);
bars.exit().remove();
bars
.attr('x', function(d) {
return xScale(d.y0);
})
.attr('y', function(d) {
return yScale(d[yColumn]);
})
.attr('width', function(d) {
return xScale(d.y);
})
.attr('height', yScale.rangeBand());
}
function listenForHover(selection, data) {
selection
.on('mouseover', function(d) {
hoveredColorValue = d;
render(data);
})
.on('mouseout', function(d) {
hoveredColorValue = null;
render(data);
})
.style('cursor', 'pointer');
}
function setOverlayTransparency(alpha) {
overlayRect
.transition()
.duration(400)
.attr('fill', 'rgba(255, 255, 255, ' + alpha + ')');
}
function type(d) {
//d.revenue = +d.revenue;
d.items = +d.items;
//d.revenue_billions = +d.revenue_billions;
d.total_items = +d.total_items;
//d.year_created = +d.year_created;
return d;
}
const dataUrl = 'items1(3).csv';
d3.csv(dataUrl, type, render);
</script>
在这段代码中,我试图
1-wvar y Scale与var xScale
1-swap var yScale with var xScale
2-wap var yAxis和var.Axis(.scale(xScale))带有.scale(yScale)
2-swap var xAxis with var yAxis and function (.scale(xScale)) with .scale(yScale)
3交换yScale.domain的xScale.domain
3-swap xScale.domain with yScale.domain
将4个xAxisG.call(xAxis)与yAxisG.call(yAxis)交换
4-swap xAxisG.call(xAxis) with yAxisG.call(yAxis)
5交换bar.attr('x'和相应的返回类型,带有bar.attr('y'和相应的返回类型
5-swap bars.attr('x' and corresponding return type with bars.attr('y' and corresponding return type
,但是它没有交换轴.如何交换轴?
but it did not swap the axis. How I can swap the axis?
推荐答案
该网站对此进行了很好的解释: https://www.d3-graph-gallery.com/barplot
This website explains it well: https://www.d3-graph-gallery.com/barplot
(比较 https://www.d3-graph-gallery.com/graph/barplot_basic.html 和 https://www.d3 -graph-gallery.com/graph/barplot_horizontal.html )
通常,您只需要像这样交换x和y轴:
In general, you just need to swap x- and y-axis like this:
垂直(x轴取data.map(d => d.Country)
,y轴取[0, 13000]
作为域):
Vertical (x-axis takes the data.map(d => d.Country)
and y-axis takes the [0, 13000]
as domain):
// X axis
var x = d3.scaleBand()
.range([ 0, width ])
.domain(data.map(function(d) { return d.Country; }))
.padding(0.2);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Add Y axis
var y = d3.scaleLinear()
.domain([0, 13000])
.range([ height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
水平(y轴取data.map(d => d.Country)
,x轴取[0, 13000]
作为域):
Horizontal (y-axis takes the data.map(d => d.Country)
and x-axis takes the [0, 13000]
as domain):
// Add X axis
var x = d3.scaleLinear()
.domain([0, 13000])
.range([ 0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Y axis
var y = d3.scaleBand()
.range([ 0, height ])
.domain(data.map(function(d) { return d.Country; }))
.padding(.1)
svg.append("g")
.call(d3.axisLeft(y))
为了进一步改进该示例,您不应将数据值的域硬编码为[0, 13000]
,而应使用d3.max()
:
To improve on that example further, you should not hard-code the domain of the data value to [0, 13000]
but rather you should use d3.max()
:
例如:
.domain([0, d3.max(data.map(d => +d.Value))])
完整示例:
垂直(x轴使用data.map(d => d.Country)
,y轴使用[0, d3.max(data.map(d => +d.Value))]
作为域):
Vertical (x-axis takes the data.map(d => d.Country)
and y-axis takes the [0, d3.max(data.map(d => +d.Value))]
as domain):
// X axis
var x = d3.scaleBand()
.range([ 0, width ])
.domain(data.map(function(d) { return d.Country; }))
.padding(0.2);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Add Y axis
var y = d3.scaleLinear()
.domain([0, d3.max(data.map(d => +d.Value))])
.range([ height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
水平(y轴取data.map(d => d.Country)
,x轴取[0, d3.max(data.map(d => +d.Value))]
作为域):
Horizontal (y-axis takes the data.map(d => d.Country)
and x-axis takes the [0, d3.max(data.map(d => +d.Value))]
as domain):
// Add X axis
var x = d3.scaleLinear()
.domain([0, d3.max(data.map(d => +d.Value))])
.range([ 0, width]);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Y axis
var y = d3.scaleBand()
.range([ 0, height ])
.domain(data.map(function(d) { return d.Country; }))
.padding(.1)
svg.append("g")
.call(d3.axisLeft(y))
更新
对于您的特定示例,我无法进行分叉.但我可以从中分叉它: -放入我自己的叉子中- https://vizhub.com/Alex-ley/444e5503a19b4b829f94f8d732e5cba3
For your particular example, I could not fork it. but I could fork the one you forked it from: https://beta.vizhub.com/curran/ef717a89e37a4d9285cebfa904790665 - into my own fork - https://vizhub.com/Alex-ley/444e5503a19b4b829f94f8d732e5cba3
输出类似:
然后我分叉了一下,并为您翻转了轴: https://vizhub.com/Alex-ley/1ebd1b410b994ce1ad4e754bd7ebf89a?edit=files&file=index.html
Then I forked this and flipped the axes for you: https://vizhub.com/Alex-ley/1ebd1b410b994ce1ad4e754bd7ebf89a?edit=files&file=index.html
现在具有如下输出:
代码中最重要的部分是:
The most important part of the code is:
function renderBars(g, layers) {
var layerGs = g.selectAll('.layer').data(layers);
layerGs
.enter()
.append('g')
.attr('class', 'layer');
layerGs.exit().remove();
const maxY = d3.max(layers, function(layer) {
return d3.max(layer.values, function(d) {
return d.y + d.y0;
});
})
console.log(maxY)
layerGs.style('fill', function(d) {
return colorScale(d.key);
});
var bars = layerGs.selectAll('rect').data(function(d) {
return d.values;
});
bars
.enter()
.append('rect')
.on('mouseover', function(d) {
tip.show(d);
// Ensure the tooltip is printed in the same x position (so it is not rendered off-screen to the left).
d3.select('.d3-tip').style('left', '200px');
})
.on('mouseout', tip.hide);
bars.exit().remove();
bars
.attr('x', function(d) {
return xScale(d[yColumn]);
})
.attr('y', function(d) {
return yScale(d.total_items - d.y0);
})
.attr('height', function(d) {
return yScale(maxY - d.y);
})
.attr('width', xScale.rangeBand());
}
这篇关于如何在d3.js中交换x和y轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!