我是 D3 的新手,我正在嘗試使用 D3 構建分組條形圖。當一個圖結束時,我需要在 X 軸上放置網格線。目前它被放置在中間。此外,目前網格線出現在繪制圖形的頂部,如何將網格線移動到圖形后面。在 Y 軸上,是否可以讓我的刻度從 1000、2000、3000、4000 開始而不是當前顯示 0.5k、1k 等
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div id="grouped-chart"></div>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
const data = [
{
category: {
model: 'A',
},
type1: '1000',
type2: '2000',
},
{
category: {
model: 'B',
},
type1: '2000',
type2: '3000',
},
{
category: {
model: 'C',
},
type1: '1500',
type2: '4000',
},
];
const margin = { top: 20, right: 30, bottom: 30, left: 60 };
const width = 400 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svg = d3
.select('#grouped-chart')
.append('svg')
.attr('width', width margin.left margin.right)
.attr('height', height margin.top margin.bottom)
.style('background', '#fff');
const g = svg
.append('g')
.attr('transform', 'translate(' margin.left ',' margin.top ')');
const x0 = d3.scaleBand().rangeRound([0, width]).paddingInner(0.1);
const x1 = d3.scaleBand().padding(0.05);
const y = d3.scaleLinear().rangeRound([height, 0]);
const z = d3.scaleOrdinal().range(['#004c6d', '#255e7e', '#3d708f']);
const keys = Object.keys(data[0]).slice(1);
x0.domain(data.map((d) => d.category.model));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([0, 4000]);
const gX = g
.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' height ')')
.call(d3.axisBottom(x0));
const gY = g
.append('g')
.attr('class', 'axis')
.call(d3.axisLeft(y).ticks(null, 's'));
g.append('g')
.attr('class', 'grid')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom().scale(x0).tickSize(-height, 0, 0).tickFormat(''));
g.append('g')
.attr('class', 'grid')
.call(d3.axisLeft().scale(y).tickSize(-width, 0, 0).tickFormat(''));
g.append('g')
.selectAll('g')
.data(data)
.enter()
.append('g')
.attr('transform', (d) => 'translate(' x0(d.category.model) ',0)')
.selectAll('rect')
.data((d) =>
keys.map((key) => {
return { key: key, value: d[key] };
})
)
.enter()
.append('rect')
.attr('x', (d) => x1(d.key))
.attr('y', (d) => y(d.value))
.attr('width', x1.bandwidth())
.attr('height', (d) => height - y(d.value))
.attr('fill', (d) => z(d.key));
</script>
</body>
</html>
uj5u.com熱心網友回復:
對于 y 軸刻度線,您可以將刻度數設定為 4。然后它們會以千為單位繪制:d3.axisLeft(y).ticks(4, 's')。您還可以顯式設定tickValues。
對于網格線,您可以復制軸創建的刻度線并調整它們的坐標以跨越整個圖表。對于垂直網格線,您可以偏移它們的 x 坐標x0.step() / 2,以便將它們放在組之間(step() docs)。
另外,我會推薦灰色刻度線而不是黑色,這樣它們就不會引起太多關注。最后,您為條形選擇的兩種顏色有點難以區分。Colorgorical和ColorBrewer等工具可用于選擇顏色。許多 ColorBrewer 方案都在d3-scale- chrom 中提供。
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<div id="grouped-chart"></div>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script>
// data
const data = [
{
category: {
model: 'A',
},
type1: '1000',
type2: '2000',
},
{
category: {
model: 'B',
},
type1: '2000',
type2: '3000',
},
{
category: {
model: 'C',
},
type1: '1500',
type2: '4000',
},
];
// set up
const margin = { top: 20, right: 30, bottom: 30, left: 60 };
const width = 400 - margin.left - margin.right;
const height = 400 - margin.top - margin.bottom;
const svg = d3.select('#grouped-chart')
.append('svg')
.attr('width', width margin.left margin.right)
.attr('height', height margin.top margin.bottom)
.style('background', '#fff');
const g = svg
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// scales
const keys = Object.keys(data[0]).slice(1);
const x0 = d3.scaleBand()
.domain(data.map((d) => d.category.model))
.rangeRound([0, width])
.paddingInner(0.1);
const x1 = d3.scaleBand()
.domain(keys)
.rangeRound([0, x0.bandwidth()])
.padding(0.05);
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => Math.max( d.type1, d.type2))])
.rangeRound([height, 0]);
const z = d3.scaleOrdinal()
.domain(keys)
// colors picked with colorgorical
.range(["rgb(88,181,225)", "rgb(26,101,135)"]);
// axes
g.append('g')
.attr('class', 'axis')
// move group to bottom of chart
.attr('transform', `translate(0,${height})`)
// add axis
.call(d3.axisBottom(x0).tickSizeOuter(0))
// copy tick marks to create grid lines
.call(g => g.selectAll('.tick > line')
// skip last tick since there's no group after it
.filter((d, i, nodes) => i < nodes.length - 1)
.clone()
.attr('stroke', '#cccccc')
// move to in between the groups
.attr('x1', x0.step() / 2)
.attr('x2', x0.step() / 2)
// make them go from top to bottom of chart
.attr('y1', -height)
.attr('y2', 0));
g.append('g')
.attr('class', 'axis')
// add axis
.call(d3.axisLeft(y).ticks(4, 's'))
// copy tick marks to create grid lines
.call(g => g.selectAll('.tick > line')
// skip first tick since there's already a baseline from the x axis
.filter((d, i) => i > 0)
.clone()
.attr('stroke', '#cccccc')
.attr('x1', 0)
.attr('x2', width));
// bars
g.append('g')
.selectAll('g')
.data(data)
.join('g')
.attr('transform', d => `translate(${x0(d.category.model)},0)`)
.selectAll('rect')
.data(d => keys.map((key) => ({ key: key, value: d[key] })))
.join('rect')
.attr('x', d => x1(d.key))
.attr('y', d => y(d.value))
.attr('width', x1.bandwidth())
.attr('height', d => height - y(d.value))
.attr('fill', d => z(d.key));
</script>
</body>
</html>
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/326030.html
標籤:javascript d3.js
上一篇:d3垂直堆積條形圖頂部的文本
