开始,x轴标签位于刻度的中间。但是,旋转x轴标签后,x轴标签显示一些问题。
现在,我希望x轴标签位于刻度线的中间。我能怎么做?
如果使用transform
,如何获取x轴的中点?
结果看起来像https://drive.google.com/open?id=1Fen0to5Ih86alOXu6UXeJzeicX1E1JFJ
const data = [
{
'group': 'G1',
'sample': 's1',
'Actinomyces': 12.55802794990189,
'Alloprevotella': 0.3671446023182472,
'Atopobium': 0.15760660109181326,
'Anaerococcus': 0
},
{
'group': 'G1',
'sample': 's2',
'Actinomyces': 9.55802794990189,
'Alloprevotella': 0.3671446023182472,
'Atopobium': 0.12760660109181326,
'Anaerococcus': 10.0
},
{
'group': 'G2',
'sample': 's3',
'Actinomyces': 11.55802794990189,
'Alloprevotella': 0.3671446023182472,
'Atopobium': 0.9760660109181326,
'Anaerococcus': 5.0
},
{
'group': 'G2',
'sample': 's4',
'Actinomyces': 19.55802794990189,
'Alloprevotella': 1.3671446023182472,
'Atopobium': 2.15760660109181326,
'Anaerococcus': 4.0
}
]
const w = 800
const h = 400
const margin = { top: 50, right: 50, bottom: 50, left: 150 }
const keys = Object.keys(data[0]).filter(function (val) {
return val !== 'sample' && val !== 'group'
})
// create a stack generator
let stack = d3.stack()
.keys(keys)
const xScale = d3.scaleBand()
.domain(d3.range(data.length))
.range([margin.left, w - margin.right])
.paddingOuter(0.02)
const yScale = d3.scaleLinear()
.domain([0,
d3.max(data, function (d) {
return d3.sum(keys.map(val => d[val]))
})
])
.range([h - margin.bottom, margin.top])
const colorScale = d3.scaleLinear()
.domain([0, keys.length - 1])
.range([0, 1])
// create svg
const svg = d3.select('#app')
.append('svg')
.attr('width', w)
.attr('height', h)
const groups = svg.selectAll('g')
.data(stack(data))
.enter()
.append('g')
.style('fill', function (d, i) {
return d3.interpolateSpectral(colorScale(i))
})
groups.selectAll('rect')
.data(function (d) {
return d
})
.enter()
.append('rect')
.attr('x', (d, i) => xScale(i))
.attr('y', d => yScale(d[1]))
.attr('height', d => yScale(d[0]) - yScale(d[1]))
.attr('width', xScale.bandwidth())
// add axis
const xAxis = d3.axisBottom(xScale)
.tickFormat(d => keys[d])
svg.append('g')
.attr('class', 'xAxis')
.attr('transform', 'translate(0, ' + yScale(0) + ')')
.call(xAxis)
.selectAll('text')
.attr('text-anchor', 'start')
.attr('dx', '10px')
.attr('transform', 'rotate(90)')
const yAxis = d3.axisLeft(yScale)
svg.append('g')
.attr('class', 'yAxis')
.attr('transform', 'translate(' + xScale(0) + ', 0)')
.call(yAxis)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="app">
</div>
答案 0 :(得分:0)
我的英语很差,所以我制作了一个转换过程图,可以在这里https://drive.google.com/open?id=19zmGFwivdjPqVabVGIgdNVXKRGdR8v2s
找到。部分代码已更改为位于
之间/** change **/
...
/***********/
const data = [
{
'group': 'G1',
'sample': 's1',
'Actinomyces': 12.55802794990189,
'Alloprevotella': 0.3671446023182472,
'Atopobium': 0.15760660109181326,
'Anaerococcus': 0
},
{
'group': 'G1',
'sample': 's2',
'Actinomyces': 9.55802794990189,
'Alloprevotella': 0.3671446023182472,
'Atopobium': 0.12760660109181326,
'Anaerococcus': 10.0
},
{
'group': 'G2',
'sample': 's3',
'Actinomyces': 11.55802794990189,
'Alloprevotella': 0.3671446023182472,
'Atopobium': 0.9760660109181326,
'Anaerococcus': 5.0
},
{
'group': 'G2',
'sample': 's4',
'Actinomyces': 19.55802794990189,
'Alloprevotella': 1.3671446023182472,
'Atopobium': 2.15760660109181326,
'Anaerococcus': 4.0
}
]
const w = 800
const h = 400
const margin = { top: 50, right: 50, bottom: 50, left: 150 }
const keys = Object.keys(data[0]).filter(function (val) {
return val !== 'sample' && val !== 'group'
})
// create a stack generator
let stack = d3.stack()
.keys(keys)
const xScale = d3.scaleBand()
.domain(d3.range(data.length))
.range([margin.left, w - margin.right])
.paddingOuter(0.02)
const yScale = d3.scaleLinear()
.domain([0,
d3.max(data, function (d) {
return d3.sum(keys.map(val => d[val]))
})
])
.range([h - margin.bottom, margin.top])
const colorScale = d3.scaleLinear()
.domain([0, keys.length - 1])
.range([0, 1])
// create svg
const svg = d3.select('#app')
.append('svg')
.attr('width', w)
.attr('height', h)
const groups = svg.selectAll('g')
.data(stack(data))
.enter()
.append('g')
.style('fill', function (d, i) {
return d3.interpolateSpectral(colorScale(i))
})
groups.selectAll('rect')
.data(function (d) {
return d
})
.enter()
.append('rect')
.attr('x', (d, i) => xScale(i))
.attr('y', d => yScale(d[1]))
.attr('height', d => yScale(d[0]) - yScale(d[1]))
.attr('width', xScale.bandwidth())
// add axis
const xAxis = d3.axisBottom(xScale)
.tickFormat(d => keys[d])
svg.append('g')
.attr('class', 'xAxis')
.attr('transform', 'translate(0, ' + yScale(0) + ')')
.call(xAxis)
/** change **/
.selectAll('text')
.attr('text-anchor', 'start')
.attr('y', 0)
.attr('transform', 'rotate(90)')
.attr('dx', 9) // let the text move a little to the bottom
.attr('dy', 2) // at the beginning, the top of text is parallel with the tick. So we need move a little to the right
/***********/
const yAxis = d3.axisLeft(yScale)
svg.append('g')
.attr('class', 'yAxis')
.attr('transform', 'translate(' + xScale(0) + ', 0)')
.call(yAxis)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="app">
</div>