Skip to content

Instantly share code, notes, and snippets.

@ecgan
Last active January 8, 2018 09:03
Show Gist options
  • Save ecgan/6da307ac465745bfc801850f4c1b57c6 to your computer and use it in GitHub Desktop.
Save ecgan/6da307ac465745bfc801850f4c1b57c6 to your computer and use it in GitHub Desktop.
Placing x-axis values and labels between tick marks
license: gpl-3.0
[
{
"value": 10,
"startDate": "2018-01-01",
"endDate": "2018-01-07",
"week": "Week 1"
}, {
"value": 5,
"startDate": "2018-01-08",
"endDate": "2018-01-14",
"week": "Week 2"
}, {
"value": 15,
"startDate": "2018-01-15",
"endDate": "2018-01-21",
"week": "Week 3"
}, {
"value": 45,
"startDate": "2018-01-22",
"endDate": "2018-01-29",
"week": "Week 4"
}, {
"value": 85,
"startDate": "2018-01-29",
"endDate": "2018-02-04",
"week": "Week 5"
}, {
"value": 70,
"startDate": "2018-02-05",
"endDate": "2018-02-11",
"week": "Week 6"
}, {
"value": 15,
"startDate": "2018-02-12",
"endDate": "2018-02-18",
"week": "Week 7"
}, {
"value": 40,
"startDate": "2018-02-19",
"endDate": "2018-02-25",
"week": "Week 8"
}, {
"value": 25,
"startDate": "2018-02-26",
"endDate": "2018-03-04",
"week": "Week 9"
}, {
"value": 30,
"startDate": "2018-03-05",
"endDate": "2018-03-11",
"week": "Week 10"
}
]
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.graph .line {
fill: none;
stroke: #CC0000;
stroke-width: 3;
}
.graph #xAxisWeek .tick.midWeek line {
display: none;
}
.graph #xAxisWeek .tick.endWeek text {
display: none;
}
</style>
</head>
<body>
<div class="graph">
<svg width="960" height="500"></svg>
</div>
<script>
let svg = d3.select("svg");
let margin = {top: 20, right: 20, bottom: 30, left: 40};
let width = svg.attr("width") - margin.left - margin.right;
let height = svg.attr("height") - margin.top - margin.bottom;
let g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
d3.json('data.json', (error, data) => {
if (error) throw error;
// massage data.
let graphData = data.map((item) => {
let start = new Date(item.startDate + 'T00:00:00');
let end = new Date(item.endDate + 'T24:00:00');
let mid = new Date((start.getTime() + end.getTime()) / 2);
return {
x: item.week,
y: item.value,
startDate: start,
endDate: end,
midDate: mid
};
});
// create scales based on data.
let yScale = d3.scaleLinear()
.rangeRound([height, 0])
.domain([0, 100])
.nice();
let xScale = d3.scaleTime()
.domain([
new Date(graphData[0].startDate),
new Date(graphData[graphData.length-1].endDate)
])
.rangeRound([0, width])
.clamp(true);
let lineGenerator = d3.line()
.x((d) => { return xScale(d.midDate); })
.y((d) => { return yScale(d.y); })
.curve(d3.curveLinear);
// generate linear graph.
g.append('g')
.attr('id', 'line')
.append('path')
.datum(graphData)
.attr('class', 'line')
.attr('d', lineGenerator);
// generate y-axis.
let yAxis = d3.axisLeft(yScale);
g.append('g')
.attr('id', 'yAxis')
.call(yAxis);
// generate x-axis.
let tickValues = graphData
.map((value) => [value.midDate, value.endDate])
.reduce((acc, cur) => {
return acc.concat(cur);
}, []);
let xAxisWeekGenerator = d3.axisBottom(xScale)
.tickValues(tickValues)
.tickSize(10)
.tickPadding(5)
.tickFormat((d, i) => {
let index = Math.floor(i / 2);
return graphData[index].x;
});
let xAxisWeekUi = g.append('g')
.attr('id', 'xAxisWeek')
.attr('transform', `translate(0, ${height})`)
.call(xAxisWeekGenerator);
xAxisWeekUi.selectAll('.tick')
.attr('class', (d, i) => {
if (i % 2 === 0) {
return 'tick midWeek';
}
return 'tick endWeek';
});
});
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment