如何在d3中左对齐y轴标签? 尝试使用.orient(left),但没有帮助。 尝试转换标签。 请帮助将标签向左对齐 例: 好 很好 非常 好1 很好1 非常1 好 很好 非常 好1 很好1 非常1 好 很好 非常 好1 很好1 非常1 好 很好 非常 好1 很好1 Very1
const data = [{name: 'Good', value: 1}, {name: 'Very Good', value: 2}, {name: 'Very', value: 1}, {name: 'Good1', value: 1}, {name: 'Very Good1', value: 2}, {name: 'Very1', value: 1}, {name: 'Good2', value: 1}, {name: 'Very Good2', value: 2}, {name: 'Very2', value: 1},{name: 'Good3', value: 1}, {name: 'Very Good3', value: 2}, {name: 'Very3', value: 1},{name: 'Good4', value: 1}, {name: 'Very Good5', value: 2}, {name: 'Very5', value: 1},{name: 'Good6', value: 1}, {name: 'Very Good6', value: 2}, {name: 'Very6', value: 1},{name: 'Good7', value: 1}, {name: 'Very Good7', value: 2}, {name: 'Very7', value: 1},{name: 'Good8', value: 1}, {name: 'Very Good8', value: 2}, {name: 'Very9', value: 1}];
// We want to center each rect around the value it's supposed to have.
// That means that we need to have a node width
let nodeWidth = 33;
let nodeHeight = 18;
if (this.viewBy !== 'Overlapping ' + this.jobOrSkill) {
nodeWidth = 60;
nodeHeight = 18;
}
let height = 1000;
const width = 620,
paddingLeft = 0,
paddingTop = 0,
margin = {
top: 20,
left: 140,
right: 40,
bottom: 40
};
if (this.totalSkills && this.totalSkills.length < 10) {
height = 250;
}
if (this.totalSkills && this.totalSkills.length > 10 && this.totalSkills.length < 20) {
height = 400;
}
if (this.totalSkills && this.totalSkills.length > 20 && this.totalSkills.length < 30) {
height = 600;
}
const innerWidth = width + (margin.left + margin.right);
const innerHeight = height + (margin.top + margin.bottom);
// We also need to make sure there is space for all nodes, even at the edges.
// One way to get this is by just extending the domain a little.
const domain = d3.extent(data.map(d => Math.round(d.value)));
const x = d3.scaleLinear()
.domain([Math.round(domain[0]) - 1, Math.round(domain[1]) + 1])
.range([0, width]);
const y = d3.scaleBand()
.domain(data.map((d, i) => d.name && d.name.length > 20 ? d.name = d.name.slice(0, 20) + '...' : d.name = d.name))
.range([height, 0])
.padding(1);
const svg = d3.select('#comparisionChartData')
.attr('width', width + margin.left)
.attr('height', height + margin.top + margin.bottom);
const g = svg
.append('g')
.attr('transform', `translate(${margin.left} ${margin.right})`);
g.append('g')
.classed('x-axis', true)
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x));
d3.selectAll('.y-axis').selectAll('.tick')
.append('svg:title')
.data(data)
.text(function (d) {
return d.name;
});
g.append('g')
.classed('y-axis', true)
.call(d3.axisLeft(y).tickPadding(10));
const bars = g.append('g')
.selectAll('rect')
.data(data)
.attr('stroke', '#e5e5e5')
.attr('class', 'line');
bars.exit().remove();
// All the same until here
bars.enter()
.append('rect')
// width has become a constant
.attr('width', nodeWidth)
// Now, transform each node so it centers around the value it's supposed to have
.attr('transform', `translate(${-nodeWidth / 2} -8)`)
// .merge(bars)
// `x` denotes the placement directly again
.attr('x', d => x(Math.round(d.value)))
.attr('y', d => y(d.name))
.attr('height', nodeHeight)
.attr('fill', d => Math.round(d.value) > 0 && this.viewBy === 'Overlapping ' + this.jobOrSkill ? '#648fff' :
this.viewBy === 'Overlapping ' + this.jobOrSkill && Math.round(d.value) === 0 ? '#9a16ca' :
this.viewBy === 'Overlapping ' + this.jobOrSkill && Math.round(d.value) < 0 ? '#dc267f' :
this.viewBy === 'Unique to Organization' ? '#016970' : this.viewBy === 'Absent to Organization' ? '#757575' : '#648fff');
// Now one more thing, we want to add labels to each node.
// `<rect>` can't have children, we we add them to the plot seperately
// using the same `data` as for the bars
const labels = g.append('g')
.selectAll('text')
.data(data);
labels.exit().remove();
labels.enter()
.append('text')
.attr('fill', 'white')
.attr('text-anchor', 'middle') // center-align the text
// .merge(bars)
// `x` denotes the placement directly
.attr('x', d => x(Math.round(d.value)))
// Add half a bar's height to target the center of each node
.attr('y', d => y(d.name) + y.bandwidth() / 4)
// Actually fill in the text this.viewBy === 'Overlapping ' + this.jobOrSkill ? '+' + Math.round(d.value) :
.text(d => Math.round(d.value) > 0 && this.viewBy === 'Overlapping ' + this.jobOrSkill ? Math.round(d.value)
: this.viewBy === 'Unique to Organization' ? 'Unique' : this.viewBy === 'Absent to Organization' ? 'Absent' : Math.round(d.value))
.attr('title', d => y(d.name))
.attr('transform', `translate(0, 0)`)
.attr('dy', 5);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="comparisionChartData"></svg>
答案 0 :(得分:0)
我能够结合使用text-anchor: start
和transform(-60, 0)
来获得它:
const data = [{
name: 'Good',
value: 1
}, {
name: 'Very Good',
value: 2
}, {
name: 'Very',
value: 1
}, {
name: 'Good1',
value: 1
}, {
name: 'Very Good1',
value: 2
}, {
name: 'Very1',
value: 1
}, {
name: 'Good2',
value: 1
}, {
name: 'Very Good2',
value: 2
}, {
name: 'Very2',
value: 1
}, {
name: 'Good3',
value: 1
}, {
name: 'Very Good3',
value: 2
}, {
name: 'Very3',
value: 1
}, {
name: 'Good4',
value: 1
}, {
name: 'Very Good5',
value: 2
}, {
name: 'Very5',
value: 1
}, {
name: 'Good6',
value: 1
}, {
name: 'Very Good6',
value: 2
}, {
name: 'Very6',
value: 1
}, {
name: 'Good7',
value: 1
}, {
name: 'Very Good7',
value: 2
}, {
name: 'Very7',
value: 1
}, {
name: 'Good8',
value: 1
}, {
name: 'Very Good8',
value: 2
}, {
name: 'Very9',
value: 1
}];
// We want to center each rect around the value it's supposed to have.
// That means that we need to have a node width
let nodeWidth = 33;
let nodeHeight = 18;
if (this.viewBy !== 'Overlapping ' + this.jobOrSkill) {
nodeWidth = 60;
nodeHeight = 18;
}
let height = 1000;
const width = 620,
paddingLeft = 0,
paddingTop = 0,
margin = {
top: 20,
left: 140,
right: 40,
bottom: 40
};
if (this.totalSkills && this.totalSkills.length < 10) {
height = 250;
}
if (this.totalSkills && this.totalSkills.length > 10 && this.totalSkills.length < 20) {
height = 400;
}
if (this.totalSkills && this.totalSkills.length > 20 && this.totalSkills.length < 30) {
height = 600;
}
const innerWidth = width + (margin.left + margin.right);
const innerHeight = height + (margin.top + margin.bottom);
// We also need to make sure there is space for all nodes, even at the edges.
// One way to get this is by just extending the domain a little.
const domain = d3.extent(data.map(d => Math.round(d.value)));
const x = d3.scaleLinear()
.domain([Math.round(domain[0]) - 1, Math.round(domain[1]) + 1])
.range([0, width]);
const y = d3.scaleBand()
.domain(data.map((d, i) => d.name && d.name.length > 20 ? d.name = d.name.slice(0, 20) + '...' : d.name = d.name))
.range([height, 0])
.padding(1);
const svg = d3.select('#comparisionChartData')
.attr('width', width + margin.left)
.attr('height', height + margin.top + margin.bottom);
const g = svg
.append('g')
.attr('transform', `translate(${margin.left} ${margin.right})`);
g.append('g')
.classed('x-axis', true)
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x));
g.append('g')
.classed('y-axis', true)
.call(d3.axisLeft(y).tickPadding(10))
.selectAll("text")
.attr("transform", "translate(-60, 0)")
.attr("text-anchor", "start")
.append("title")
.text(function(d) {
return d;
});
const bars = g.append('g')
.selectAll('rect')
.data(data)
.attr('stroke', '#e5e5e5')
.attr('class', 'line');
bars.exit().remove();
// All the same until here
bars.enter()
.append('rect')
// width has become a constant
.attr('width', nodeWidth)
// Now, transform each node so it centers around the value it's supposed to have
.attr('transform', `translate(${-nodeWidth / 2} -8)`)
// .merge(bars)
// `x` denotes the placement directly again
.attr('x', d => x(Math.round(d.value)))
.attr('y', d => y(d.name))
.attr('height', nodeHeight)
.attr('fill', d => Math.round(d.value) > 0 && this.viewBy === 'Overlapping ' + this.jobOrSkill ? '#648fff' :
this.viewBy === 'Overlapping ' + this.jobOrSkill && Math.round(d.value) === 0 ? '#9a16ca' :
this.viewBy === 'Overlapping ' + this.jobOrSkill && Math.round(d.value) < 0 ? '#dc267f' :
this.viewBy === 'Unique to Organization' ? '#016970' : this.viewBy === 'Absent to Organization' ? '#757575' : '#648fff');
// Now one more thing, we want to add labels to each node.
// `<rect>` can't have children, we we add them to the plot seperately
// using the same `data` as for the bars
const labels = g.append('g')
.selectAll('text')
.data(data);
labels.exit().remove();
labels.enter()
.append('text')
.attr('fill', 'white')
.attr('text-anchor', 'middle') // center-align the text
// .merge(bars)
// `x` denotes the placement directly
.attr('x', d => x(Math.round(d.value)))
// Add half a bar's height to target the center of each node
.attr('y', d => y(d.name) + y.bandwidth() / 4)
// Actually fill in the text this.viewBy === 'Overlapping ' + this.jobOrSkill ? '+' + Math.round(d.value) :
.text(d => Math.round(d.value) > 0 && this.viewBy === 'Overlapping ' + this.jobOrSkill ? Math.round(d.value) :
this.viewBy === 'Unique to Organization' ? 'Unique' : this.viewBy === 'Absent to Organization' ? 'Absent' : Math.round(d.value))
.attr('title', d => y(d.name))
.attr('transform', `translate(0, 0)`)
.attr('dy', 5);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg id="comparisionChartData"></svg>