add visitor & pageview data to chart, combined.

This commit is contained in:
Danny van Kooten 2016-12-05 16:34:41 +01:00
parent b40ef9f84c
commit 1d2fd050f2
2 changed files with 77 additions and 40 deletions

View File

@ -18,6 +18,7 @@ class Graph extends Component {
} }
this.fetchData = this.fetchData.bind(this); this.fetchData = this.fetchData.bind(this);
this.refreshChart = this.refreshChart.bind(this);
} }
componentDidMount() { componentDidMount() {
@ -31,59 +32,90 @@ class Graph extends Component {
} }
refreshChart() { refreshChart() {
var padt = 20, padb = 40, padr = 40, padl = 40, var padt = 10, padb = 20, padr = 40, padl = 40,
h = 300, h = 300,
w = document.getElementById('graph').parentNode.clientWidth - padl - padr, w = document.getElementById('graph').parentNode.clientWidth - padl-padr,
x = d3.scaleBand().range([0, w]).padding(0.2), x = d3.scaleBand().range([0, w]).padding(0.2).round(true),
y = d3.scaleLinear().range([h, 0]), y = d3.scaleLinear().range([h, 0]),
yAxis = d3.axisLeft().scale(y).tickSize(-w + padl + padr), yAxis = d3.axisLeft().scale(y).tickSize(-w + padl + padr),
xAxis = d3.axisBottom().scale(x), xAxis = d3.axisBottom().scale(x),
xTick = Math.round(this.state.visitorData.length / 7); visitorData = this.state.visitorData,
pageviewData = this.state.pageviewData,
xTick = Math.round(pageviewData.length / 7);
var tip = d3.tip() var pageviewTip = d3.tip()
.attr('class', 'd3-tip')
.html(function(d) { return '<span>' + d.Count + '</span>' + ' pageviews' })
.offset([-12, 0]);
var visitorTip = d3.tip()
.attr('class', 'd3-tip') .attr('class', 'd3-tip')
.html(function(d) { return '<span>' + d.Count + '</span>' + ' visitors' }) .html(function(d) { return '<span>' + d.Count + '</span>' + ' visitors' })
.offset([-12, 0]); .offset([-12, 0]);
var vis = d3.select('#graph') var graph = d3.select('#graph');
// remove previous graph
graph.selectAll('*').remove();
var vis = graph
.append('svg') .append('svg')
.attr('width', w) .attr('width', w + padl + padr)
.attr('height', h + padt + padb) .attr('height', h + padt + padb)
.append('g') .append('g')
.attr('transform', 'translate(' + padl + ',' + padt + ')'); .attr('transform', 'translate(' + padl + ',' + padt + ')');
vis.call(tip); vis.call(pageviewTip);
vis.call(visitorTip);
var max = d3.max(this.state.visitorData, function(d) { return d.Count }); var max = d3.max(pageviewData, function(d) { return d.Count });
x.domain(this.state.visitorData.map((d) => d.Label)) x.domain(pageviewData.map((d) => d.Label))
y.domain([0, max]) y.domain([0, (max * 1.1)])
var barWidth = x.bandwidth();
// axes // axes
vis.selectAll('g.axis').remove();
vis.append("g") vis.append("g")
.attr("class", "y axis") .attr("class", "y axis")
.call(yAxis); .call(yAxis);
vis.append("g") vis.append("g")
.attr("class", "x axis") .attr("class", "x axis")
.attr('transform', 'translate(0,' + h + ')') .attr('transform', 'translate(0,' + h + ')')
.call(xAxis) .call(xAxis)
.selectAll('g') .selectAll('g')
.style('display', (d, i) => i % xTick != 0 ? 'none' : 'block') .style('display', (d, i) => i % xTick != 0 ? 'none' : 'block')
// bars // bars
var data = this.state.visitorData; vis.selectAll('g.primary-bar').remove();
var bars = vis.selectAll('g.bar') var bars = vis.selectAll('g.primary-bar')
.data(data) .data(pageviewData)
.enter().append('g') .enter().append('g')
.attr('class', 'bar') .attr('class', 'primary-bar')
.attr('transform', function (d, i) { return "translate(" + x(d.Label) + ", 0)" }); .attr('transform', function (d, i) { return "translate(" + x(d.Label) + ", 0)" });
bars.append('rect') bars.append('rect')
.attr('width', () => x.bandwidth() ) .attr('width', barWidth)
.attr('height', (d) => (h - y(d.Count)) ) .attr('height', (d) => (h - y(d.Count)) )
.attr('y', (d) => y(d.Count)) .attr('y', (d) => y(d.Count))
.on('mouseover', tip.show) .on('mouseover', pageviewTip.show)
.on('mouseout', tip.hide) .on('mouseout', pageviewTip.hide);
vis.selectAll('g.sub-bar').remove();
var visitorBars = vis.selectAll('g.sub-bar')
.data(visitorData)
.enter().append('g')
.attr('class', 'sub-bar')
.attr('transform', (d, i) => "translate(" + ( x(d.Label) + ( barWidth / 4 ) ) + ", 0)");
visitorBars.append('rect')
.attr('width', barWidth / 2 )
.attr('height', (d) => (h - y(d.Count)) )
.attr('y', (d) => y(d.Count))
.on('mouseover', visitorTip.show)
.on('mouseout', visitorTip.hide);
} }
fetchData(period) { fetchData(period) {
@ -100,22 +132,22 @@ class Graph extends Component {
throw new Error(); throw new Error();
}).then((data) => { }).then((data) => {
this.setState({ visitorData: data }) this.setState({ visitorData: data })
window.requestAnimationFrame(this.refreshChart.bind(this)); window.requestAnimationFrame(this.refreshChart);
}); });
// // fetch pageview data // fetch pageview data
// fetch(`/api/pageviews/count/day?before=${before}&after=${after}`, { fetch(`/api/pageviews/count/day?before=${before}&after=${after}`, {
// credentials: 'include' credentials: 'include'
// }).then((r) => { }).then((r) => {
// if( r.ok ) { if( r.ok ) {
// return r.json(); return r.json();
// } }
//
// throw new Error(); throw new Error();
// }).then((data) => { }).then((data) => {
// this.setState({ pageviewData: data }) this.setState({ pageviewData: data })
// window.requestAnimationFrame(this.refreshChart.bind(this)); window.requestAnimationFrame(this.refreshChart);
// }); });
} }
render() { render() {

View File

@ -13,12 +13,17 @@
fill: #888; fill: #888;
} }
rect { rect {
fill: #339cff; fill: lighten( #339cff, 10%);
fill-opacity: 0.7; fill-opacity: 0.5;
} }
rect:hover { rect:hover {
fill-opacity: 1; fill-opacity: 1;
} }
.sub-bar rect {
fill: darken(#339cff, 20%);
}
.d3-tip { .d3-tip {
line-height: 1; line-height: 1;
font-weight: bold; font-weight: bold;