我正在更新由以前的开发人员编写的d3图形。作为非专家ind d3,我很难找到解决问题的答案。我想做的一件事是更改x轴刻度以从状态中拾取字符串值,但是,我尝试的所有操作都会破坏图表。
数据:
let extractedData = [
{ label: '2018-7-3', wage: 7.5 },
{ label: '2018-5-3', wage: 6.1 },
{ label: '2018-1-3', wage: 5.3 },
{ label: '2018-11-3', wage: 6.1 }
];
标签应成为x轴刻度线。
const x_scale = d3
.scaleLinear()
.domain([0, 4])
.range([padding, chart_width - 3 * padding]);
const x_axis = d3
.axisBottom(x_scale)
.ticks(4)
.tickSize(1)
构建此图表的整个代码块为:
const x_scale = d3
.scaleLinear()
.domain(data.map(function (d) { return d.label; }))
.range([padding, chart_width - 3 * padding]);
const y_scale = d3
.scaleLinear()
.domain([0, wages])
.range([chart_height - 2 * padding, padding]);
const svg = d3
.select('#lineChart')
.append('svg')
.attr('width', chart_width)
.attr('height', chart_height)
.attr('viewBox', '0 0 700 700');
//create axes
const x_axis = d3
.axisBottom(x_scale)
.ticks(4)
.tickSize(0)
.tickFormat(function (d) {
return d;
});
const y_axis = d3
.axisLeft(y_scale)
.ticks(10)
.tickSize(0)
.tickFormat(function (d) {
return '£' + d;
});
//draw axes
svg
.append('g')
.attr('class', 'xAxis')
.attr(
'transform',
'translate(' + padding + ', ' + (chart_height - 2 * padding) + ')'
)
.call(x_axis);
svg
.append('g')
.attr('class', 'yAxis')
.attr('transform', 'translate(' + 2 * padding + ',0)')
.call(y_axis);
svg
.select('.xAxis')
.selectAll('text')
.attr('transform', 'translate(0,10)')
.attr('font-size', '1.5rem');
svg
.select('.yAxis')
.selectAll('text')
.attr('transform', 'translate(-10,0)')
.attr('font-size', '1.5rem');
//create circles
svg
.selectAll('circle') // selecting the cicles that dont yet exist. sending the data to the waiting room to wait for circles to be created
.data(data)
.enter()
.append('circle')
.attr('cx', function (d) {
return x_scale(d.label); // d3 can work out which number to use on the axis to plot correctly
})
.attr('cy', function (d) {
return y_scale(d.wage);
})
.attr('r', 10)
.attr('fill', '#FFD254');
//create labels for circles
svg
.append('g') // first create, append and select a group
.selectAll('text') // then when you do 'select all text' you know that no text exists in this group because it has just been created
.data(data)
.enter()
.append('text')
.text(function (d) {
return '£' + d.wage;
})
.attr('x', function (d) {
return x_scale(d.label) + padding / 3;
})
.attr('y', function (d) {
return y_scale(d.wage);
})
.attr('font-size', '1.5rem');
//create horizontal line
svg
.append('line')
.attr('x1', padding * 2)
.attr('x2', chart_width - 2 * padding)
.attr('y1', y_scale(min_wage))
.attr('y2', y_scale(min_wage))
.style('stroke', 'red')
.style('stroke-width', '2px');
svg
.append('text')
.attr(
'transform',
'translate(' +
(chart_width - 2 * padding) +
' ,' +
(chart_height - padding / 2) +
')'
)
.style('text-anchor', 'middle')
.style('font-size', '1.5rem')
.text('Month');
})
};
答案 0 :(得分:1)
使用边距始终是一个好习惯
margin = {top: 20, right: 20, bottom: 30, left: 70},
基于这些边距,我为所有元素创建了一个组
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
问题中最重要的要求:字符串作为轴刻度线
正如@ rioV8也在评论中提到的,最好使用序数标度。
const x_scale = d3
.scaleBand()
.domain(data.map(function (d) { return d.label; }))
.rangeRound([0, chart_width]).padding(0.1);
将yScale
域设置为工资的程度,并使用d3 nice舍入值:
const y_scale = d3
.scaleLinear()
.domain(d3.extent(data, function (d) { return +d.wage; })).nice()
.rangeRound([chart_height, 0]);
将所有圈子/文字移动到组内
var circlesGroup = g.append('g').classed('circles', true);
//create circles
circlesGroup.selectAll('circle') ....
将'text-anchor'更改为X轴文本(月份)为'end'以对齐它
.style('text-anchor', 'end')
您没有设置min_wage
-因此我将其设置为7
将以上所有内容放在一起,下面是一个代码段:
var width = 900,
height = 550,
padding = 0,
margin = {top: 20, right: 20, bottom: 30, left: 70},
min_wage = 7;
var chart_height = height-margin.top-margin.bottom,
chart_width = width-margin.left-margin.right;
let data = [
{ label: '2018-7-3', wage: 7.5 },
{ label: '2018-5-3', wage: 6.1 },
{ label: '2018-1-3', wage: 5.3 },
{ label: '2018-11-3', wage: 6.1 }
];
const x_scale = d3.scaleBand()
.domain(data.map(function (d) { return d.label; }))
.rangeRound([0, chart_width]).padding(0.1);
const y_scale = d3
.scaleLinear()
.domain(d3.extent(data, function (d) { return +d.wage; })).nice()
.rangeRound([chart_height, 0]);
const svg = d3
.select('#lineChart')
.append('svg')
.attr('width', width)
.attr('height', height);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
//create axes
const x_axis = d3
.axisBottom(x_scale)
.ticks(4)
.tickFormat(function (d) {
return d;
});
const y_axis = d3
.axisLeft(y_scale)
.ticks(10)
.tickSize(0)
.tickFormat(function (d) {
return '£' + d;
});
//draw axes
g
.append('g')
.attr('class', 'xAxis')
.attr(
'transform',
'translate(0, ' + (chart_height) + ')'
)
.call(x_axis);
g
.append('g')
.attr('class', 'yAxis')
.call(y_axis);
g
.select('.xAxis')
.selectAll('text')
.attr('transform', 'translate(0,10)')
.attr('font-size', '1.5rem');
g
.select('.yAxis')
.selectAll('text')
.attr('transform', 'translate(-10,0)')
.attr('font-size', '1.5rem');
var circlesGroup = g.append('g').classed('circles', true);
//create circles
circlesGroup
.selectAll('circle') // selecting the cicles that dont yet exist. sending the data to the waiting room to wait for circles to be created
.data(data)
.enter()
.append('circle')
.attr('cx', function (d) {
return x_scale(d.label)+x_scale.bandwidth()/2; // d3 can work out which number to use on the axis to plot correctly
})
.attr('cy', function (d) {
return y_scale(d.wage);
})
.attr('r', 10)
.attr('fill', '#FFD254');
var textsGroup = g.append('g').classed('texts', true);
//create labels for circles
textsGroup
.append('g') // first create, append and select a group
.selectAll('text') // then when you do 'select all text' you know that no text exists in this group because it has just been created
.data(data)
.enter()
.append('text')
.text(function (d) {
return '£' + d.wage;
})
.attr('x', function (d) {
return x_scale(d.label) + x_scale.bandwidth()/2;
})
.attr('y', function (d) {
return y_scale(d.wage);
})
.attr('font-size', '1.5rem');
//create horizontal line
g
.append('line')
.attr('x1', 0)
.attr('x2', chart_width)
.attr('y1', y_scale(min_wage))
.attr('y2', y_scale(min_wage))
.style('stroke', 'red')
.style('stroke-width', '2px');
g
.append('text')
.attr(
'transform',
'translate(' +
(chart_width - 2 * padding) +
' ,' +
(chart_height - padding / 2) +
')'
)
.style('text-anchor', 'end')
.style('font-size', '1.5rem')
.text('Month');
text {
font-size: 12px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="lineChart">
</div>
编辑: 使用比例带宽更改了圆圈和标签的位置:
.attr('x', function (d) {
return x_scale(d.label) + x_scale.bandwidth()/2;
})
(将tickSize更改为6以确保上面的编辑有效)
希望这会有所帮助。