mirror of
https://github.com/status-im/fathom.git
synced 2025-03-01 03:20:27 +00:00
improve chart ticks & tooltip content
This commit is contained in:
parent
be3b39e669
commit
9b7acf21e4
75
assets/src/js/components/Chart.js
vendored
75
assets/src/js/components/Chart.js
vendored
@ -12,35 +12,49 @@ const formatMonth = d3.timeFormat("%b"),
|
|||||||
formatMonthDay = d3.timeFormat("%b %e");
|
formatMonthDay = d3.timeFormat("%b %e");
|
||||||
|
|
||||||
const t = d3.transition().duration(600).ease(d3.easeQuadOut);
|
const t = d3.transition().duration(600).ease(d3.easeQuadOut);
|
||||||
const xTickFormat = (len) => {
|
|
||||||
return {
|
|
||||||
hour: (d, i) => {
|
|
||||||
if(len <= 24 && d.getHours() == 0 || d.getHours() == 12) {
|
|
||||||
return d.getHours() + ":00";
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i === 0 || i === len-1) {
|
function xTickFormat(tickStep, n) {
|
||||||
|
let formatters = {
|
||||||
|
hour: (d, i) => {
|
||||||
|
if(i === 0 || i === n-1) {
|
||||||
return formatMonthDay(d);
|
return formatMonthDay(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(n <= 24 && d.getHours() === 0 || d.getHours() === 12) {
|
||||||
|
return d.getHours() + ":00";
|
||||||
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
|
|
||||||
day: (d, i) => {
|
day: (d, i, o) => {
|
||||||
if(i === 0 || i === len-1) {
|
if( i === 0 || i === n-1) {
|
||||||
return formatMonthDay(d);
|
return formatMonthDay(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
month: (d, i) => {
|
month: (d, i) => {
|
||||||
if(len>24) {
|
if(n>28) {
|
||||||
return d.getFullYear();
|
return d.getFullYear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return d.getMonth() === 0 ? d.getFullYear() : formatMonth(d);
|
return d.getMonth() === 0 ? d.getFullYear() : formatMonth(d);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return formatters[tickStep];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const incrementers = {
|
||||||
|
'hour': d => d.setHours(d.getHours() + 1),
|
||||||
|
'day': d => d.setDate(d.getDate() + 1),
|
||||||
|
'month': d => d.setMonth(d.getMonth() + 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
function incrementDate(date, incr) {
|
||||||
|
return incrementers[incr](date);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Chart extends Component {
|
class Chart extends Component {
|
||||||
@ -98,20 +112,7 @@ class Chart extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
nextDate = new Date(currentDate)
|
nextDate = new Date(currentDate)
|
||||||
|
nextDate = incrementDate(nextDate, this.state.tickStep)
|
||||||
switch(this.state.tickStep) {
|
|
||||||
case 'hour':
|
|
||||||
nextDate.setHours(nextDate.getHours() + 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'day':
|
|
||||||
nextDate.setDate(nextDate.getDate() + 1);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'month':
|
|
||||||
nextDate.setMonth(nextDate.getMonth() + 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// grab data that falls between currentDate & nextDate
|
// grab data that falls between currentDate & nextDate
|
||||||
for(let i=data.length-offset-1; i>=0; i--) {
|
for(let i=data.length-offset-1; i>=0; i--) {
|
||||||
@ -163,21 +164,25 @@ class Chart extends Component {
|
|||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
this.tip = d3.tip().attr('class', 'd3-tip').html((d) => {
|
this.tip = d3.tip().attr('class', 'd3-tip').html((d) => {
|
||||||
let title = d.Date.toLocaleDateString();
|
let title;
|
||||||
|
|
||||||
if(this.state.tickStep === 'hour') {
|
if(this.state.tickStep === 'hour') {
|
||||||
title += ` ${d.Date.getHours()}:00 - ${d.Date.getHours() + 1}:00`
|
title = `${d.Date.toLocaleDateString()} ${d.Date.getHours()}:00 - ${d.Date.getHours() + 1}:00`
|
||||||
}
|
} else if(this.state.tickStep === 'day' ) {
|
||||||
|
title = `${d.Date.toLocaleDateString()} (${d3.timeFormat("%a")(d.Date)})`
|
||||||
|
} else {
|
||||||
|
title = d3.timeFormat("%B %Y")(d.Date)
|
||||||
|
}
|
||||||
|
|
||||||
return (`
|
return (`
|
||||||
<div class="tip-heading">${title}</div>
|
<div class="tip-heading">${title}</div>
|
||||||
<div class="tip-content">
|
<div class="tip-content">
|
||||||
<div class="tip-pageviews">
|
<div class="tip-pageviews">
|
||||||
<div class="tip-number">${d.Pageviews}</div>
|
<div class="tip-number">${numbers.formatPretty(d.Pageviews)}</div>
|
||||||
<div class="tip-metric">Pageviews</div>
|
<div class="tip-metric">Pageviews</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="tip-visitors">
|
<div class="tip-visitors">
|
||||||
<div class="tip-number">${d.Visitors}</div>
|
<div class="tip-number">${numbers.formatPretty(d.Visitors)}</div>
|
||||||
<div class="tip-metric">Visitors</div>
|
<div class="tip-metric">Visitors</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`
|
</div>`
|
||||||
@ -201,11 +206,13 @@ class Chart extends Component {
|
|||||||
let x = this.x.domain(data.map(d => d.Date))
|
let x = this.x.domain(data.map(d => d.Date))
|
||||||
let y = this.y.domain([0, max*1.1])
|
let y = this.y.domain([0, max*1.1])
|
||||||
let yAxis = d3.axisLeft().scale(y).ticks(3).tickSize(-innerWidth).tickFormat(v => numbers.formatPretty(v))
|
let yAxis = d3.axisLeft().scale(y).ticks(3).tickSize(-innerWidth).tickFormat(v => numbers.formatPretty(v))
|
||||||
let xAxis = d3.axisBottom().scale(x).tickFormat(xTickFormat(data.length)[this.state.tickStep])
|
let xAxis = d3.axisBottom().scale(x).tickFormat(xTickFormat(this.state.tickStep, data.length))
|
||||||
|
|
||||||
// only show first and last tick if we have more than 24 ticks to show
|
// only show first and last tick if we have more than 28 ticks to show
|
||||||
if(data.length > 24) {
|
if(data.length > 28) {
|
||||||
xAxis.tickValues(data.map(d => d.Date).filter((d, i) => i === 0 || i === data.length-1))
|
let tickValues = data.map(d => d.Date).filter((d, i) => i === 0 || i === data.length-1);
|
||||||
|
xAxis.tickValues(tickValues)
|
||||||
|
xAxis.tickFormat(xTickFormat(this.state.tickStep, tickValues.length))
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty previous graph
|
// empty previous graph
|
||||||
|
@ -220,9 +220,9 @@ class DatePicker extends Component {
|
|||||||
<li><Pikadayer value={this.dateValue(state.startDate)} onSelect={this.setStartDate} /> <span>›</span> <Pikadayer value={this.dateValue(state.endDate)} onSelect={this.setEndDate} /></li>
|
<li><Pikadayer value={this.dateValue(state.startDate)} onSelect={this.setStartDate} /> <span>›</span> <Pikadayer value={this.dateValue(state.endDate)} onSelect={this.setEndDate} /></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul>
|
<ul>
|
||||||
{state.diff < 30 ? (<li class={classNames({ current: 'hour' === state.groupBy })}><a href="#" data-value="hour" onClick={this.setGroupBy}>Hourly</a></li>) : ''}
|
{state.diff < 31 ? (<li class={classNames({ current: 'hour' === state.groupBy })}><a href="#" data-value="hour" onClick={this.setGroupBy}>Hourly</a></li>) : ''}
|
||||||
<li class={classNames({ current: 'day' === state.groupBy })}><a href="#" data-value="day" onClick={this.setGroupBy}>Daily</a></li>
|
<li class={classNames({ current: 'day' === state.groupBy })}><a href="#" data-value="day" onClick={this.setGroupBy}>Daily</a></li>
|
||||||
{state.diff >= 30 ? (<li class={classNames({ current: 'month' === state.groupBy })}><a href="#" data-value="month" onClick={this.setGroupBy}>Monthly</a></li>) : ''}
|
{state.diff >= 31 ? (<li class={classNames({ current: 'month' === state.groupBy })}><a href="#" data-value="month" onClick={this.setGroupBy}>Monthly</a></li>) : ''}
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
)
|
)
|
||||||
|
@ -11,7 +11,7 @@ function formatPretty(num) {
|
|||||||
if (num >= M) {
|
if (num >= M) {
|
||||||
num /= M
|
num /= M
|
||||||
decimals = 3 - ((Math.round(num) + "").length) || 0;
|
decimals = 3 - ((Math.round(num) + "").length) || 0;
|
||||||
return num.toFixed(decimals > -1 ? decimals : 0).replace(rx, '') + 'M';
|
return (num.toFixed(decimals > -1 ? decimals : 0).replace(rx, '') + 'M').replace('.00', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num >= (K * 10)) {
|
if (num >= (K * 10)) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user