修复D3 JS的x轴,并将虚线添加到y轴和x轴 [英] Fix the x-axis of D3 JS and add dotted lines to the y-axis and x-axis
问题描述
有关如何在D3 JS中执行以下实现的任何帮助?
Any help on how to do below implementations in D3 JS?
- 修复不应滚动的x轴的位置
- 在x轴上的值例如-2.5,-2.0,-1.5,-1.0、0、1.0、1.5、2.0、2.5预期为:-2.5%,2.0%,-1.5%,-1.0%,0%,1.0%,1.5%,2.0%,2.5%
- 如何在y轴上添加虚线?
密码笔: https://codepen.io/nchetankumar/pen/PozGmdy
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);
推荐答案
1-我不太理解第一个问题,因为xAxis似乎固定而不滚动.
1 - I dont quite understand the first question, because the xAxis seem to be fixed and not scrolling.
2-x轴值似乎都是正的.但是,如果您像这样调用x轴刻度,则可以使用价位获得所需的格式:
2 - The x-axis values seem to be all positive. But nevertheless you can get the desired format with the vales if you call the x-axis ticks like that:
.call(d3.axisBottom(x).tickFormat(function(d) { return d+"%" }));
如果值是负数,也会显示负号.
This will also show the minus if the value is negative.
我个人建议将价位映射到1的分数(2.5%将是0.025),并且只是:
I'd personally recommend to map the vales to fractions of 1 (2.5% would be 0.025 ) and just:
.call(d3.axisBottom(x).tickFormat(d3.format(".0%"));
3-对于网格线,您可以在此处查看示例代码: https://bl.ocks.org/d3noob/879316f32be861b6870c98a277076d1b 和 .attr('stroke-dasharray'='2');
3 - For gridlines you can see sample code here: https://bl.ocks.org/d3noob/879316f32be861b6870c98a277076d1b with .attr('stroke-dasharray'='2');
这篇关于修复D3 JS的x轴,并将虚线添加到y轴和x轴的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!