Reputation:
I want to create a linechart using this data:
var mydata = [
{
"year": "2019",
"myvalue": "50"
},
{
"year": "2018",
"myvalue": "50"
},
{
"year": "2017",
"myvalue": "NaN"
},
{
"year": "2016",
"myvalue": "NaN"
},
{
"year": "2015",
"myvalue": "10"
},
{
"year": "2014",
"myvalue": "25.6"
},
{
"year": "2013",
"myvalue": "4.2"
},
{
"year": "2012",
"myvalue": "60"
},
{
"year": "2011",
"myvalue": "826"
},
{
"year": "2010",
"myvalue": "32"
},
{
"year": "2009",
"myvalue": "50"
},
{
"year": "2008",
"myvalue": "70"
}
];
Entire code HERE.
The chart I build works but it has some problems: some x
axis ticks are missing and linechart (and circle) are not allineated to x
axis (as you can see in this image):
Upvotes: 2
Views: 643
Reputation: 102194
Your code needs a lot of refactor. However, addressing only the problem stated in your question, you have 3 issues here:
You are applying the margins to a <g>
element, and then applying it again to the axis group. Drop the translate
here:
thisSvg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + margin.left + ', 0)')
You are not parsing your dates. When calling your scales the year
values are strings, not date objects. Parse the dates:
mydata.forEach(function(d) {
d.year = parseTime(d.year)
})
You cannot call your axes without setting the scale's domains first.
All together, this is your code with those changes:
var mydata = [{
"year": "2019",
"myvalue": "50"
},
{
"year": "2018",
"myvalue": "50"
},
{
"year": "2017",
"myvalue": "NaN"
},
{
"year": "2016",
"myvalue": "NaN"
},
{
"year": "2015",
"myvalue": "10"
},
{
"year": "2014",
"myvalue": "25.6"
},
{
"year": "2013",
"myvalue": "4.2"
},
{
"year": "2012",
"myvalue": "60"
},
{
"year": "2011",
"myvalue": "826"
},
{
"year": "2010",
"myvalue": "32"
},
{
"year": "2009",
"myvalue": "50"
},
{
"year": "2008",
"myvalue": "70"
}
];
var margin = {
top: 10,
right: 10,
bottom: 50,
left: 40
};
var svg = d3.select('#linechart')
.append('svg')
.attr('width', 600)
.attr('height', 200);
var parseTime = d3.timeParse("%Y");
mydata.forEach(function(d) {
d.year = parseTime(d.year)
})
var values = createAxisLine(svg);
var x = values[0];
var y = values[1];
var width = values[2];
var height = values[3];
var svg2 = values[4];
createChartLine(svg, x, y, width, height, svg2);
function createAxisLine(thisSvg) {
var width = thisSvg.attr('width') - margin.left - margin.right;
var height = thisSvg.attr('height') - margin.top - margin.bottom;
thisSvg = thisSvg.append('g').attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
var x = d3.scaleTime()
.rangeRound([0, width]);
var y = d3.scaleLinear()
.rangeRound([height, 0]);
x.domain(d3.extent(mydata, function(d) {
return d.year;
}));
y.domain([0, 1000]);
var xAxis = d3.axisBottom(x); //.tickSize(0, 0);
var yAxis = d3.axisLeft(y);
thisSvg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0, ' + height + ')')
.call(xAxis)
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '-.8em')
.attr('dy', '.15em')
.attr('transform', 'rotate(-65)');
thisSvg.append('g')
.attr('class', 'y axis')
.call(yAxis)
.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 6)
.attr('dy', '.71em')
.style('text-anchor', 'end');
return [x, y, width, height, thisSvg];
}
function createChartLine(thisSvg, x, y, width, height, thisSvg) {
var lines = thisSvg
.attr('transform', function(d) {
return 'translate(' + margin.left + ', ' + margin.top + ')';
});
var line = d3.line()
.x(function(d) {
return x(d.year);
})
.y(function(d) {
return y(d.myvalue);
})
.defined(function(d) { // for missing (0) data
if (isNaN(d.myvalue)) {
d.myvalue = 0;
}
return d.myvalue !== 0;
});
lines.append('path')
.data([mydata])
.attr('class', 'mylines')
.attr('fill', 'none')
.attr('stroke', 'steelblue')
.attr('stroke-width', 1.5)
.attr('d', line);
thisSvg.append('g').attr('class', 'circles')
.selectAll('.dot')
.data(mydata)
.enter()
.append('circle')
.attr('class', 'dot')
.attr('cx', function(d) {
return x(d.year);
})
.attr('cy', function(d) {
return y(d.myvalue);
})
.attr('r', 3);
}
<script src='https://d3js.org/d3.v5.js' charset='utf-8'></script>
<div style='height:50px;'></div>
<div id='linechart'></div>
Upvotes: 3