[WIP] typescript
This commit is contained in:
parent
e621712b9c
commit
3b927a6372
@ -1,85 +1,81 @@
|
|||||||
import * as d3 from 'd3';
|
import * as d3 from 'd3';
|
||||||
|
|
||||||
const margin = { top: 20, right: 20, bottom: 50, left: 50 },
|
export interface Data {
|
||||||
width = 960 - margin.left - margin.right,
|
date: Date;
|
||||||
height = 500 - margin.top - margin.bottom;
|
km: number;
|
||||||
|
}
|
||||||
|
|
||||||
const parseTime = d3.timeParse('%Y-%m-%d');
|
let data = [
|
||||||
|
{ date: new Date('2023-01-01'), km: 5 },
|
||||||
|
{ date: new Date('2023-02-01'), km: 24 },
|
||||||
|
{ date: new Date('2023-08-30'), km: 4000 },
|
||||||
|
];
|
||||||
|
|
||||||
data.forEach((d: any) => {
|
if(sessionStorage.getItem('userStats')) {
|
||||||
d.date = parseTime(d.date);
|
data = JSON.parse(sessionStorage.getItem('userStats') as Data[]);
|
||||||
d.km = +d.km;
|
|
||||||
});
|
|
||||||
|
|
||||||
const x = d3.scaleTime()
|
const margin = { top: 20, right: 20, bottom: 50, left: 50 };
|
||||||
.domain(d3.extent(data, d => d.date))
|
const width: number = 960 - margin.left - margin.right;
|
||||||
.range([0, width]);
|
const height: number = 500 - margin.top - margin.bottom;
|
||||||
|
|
||||||
|
data.forEach((d: Data) => {
|
||||||
|
d.date = <Date> new Date(d.date)
|
||||||
|
d.km = +d.km;
|
||||||
|
});
|
||||||
|
|
||||||
|
const x = d3.scaleTime()
|
||||||
|
.domain(<[Date, Date]>d3.extent(data, (d: Data) => d.date))
|
||||||
|
.range([0, width]);
|
||||||
|
|
||||||
|
const y = d3.scaleLinear()
|
||||||
|
.domain([0, Number(d3.max(data, (d: Data) => d.km))])
|
||||||
|
.range([height, 0]);
|
||||||
|
|
||||||
|
const line = d3.line<Data>()
|
||||||
|
.x((d: Data) => x(d.date))
|
||||||
|
.y((d: Data) => y(d.km));
|
||||||
|
|
||||||
|
const svg = d3.select('#container')
|
||||||
|
.append('svg')
|
||||||
|
.attr('width', width + margin.left + margin.right)
|
||||||
|
.attr('height', height + margin.top + margin.bottom)
|
||||||
|
.call(responsivefy)
|
||||||
|
.append('g')
|
||||||
|
.attr('transform', `translate(${margin.left},${margin.top})`);
|
||||||
|
|
||||||
|
svg.append('path')
|
||||||
|
.data([data])
|
||||||
|
.attr('class', 'line')
|
||||||
|
.attr('d', line);
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.attr('transform', `translate(0,${height})`)
|
||||||
|
.call(d3.axisBottom(x));
|
||||||
|
|
||||||
|
svg.append('g')
|
||||||
|
.call(d3.axisLeft(y));
|
||||||
|
}
|
||||||
|
|
||||||
const y = d3.scaleLinear()
|
|
||||||
.domain([0, d3.max(data, d => d.km)])
|
|
||||||
.range([height, 0]);
|
|
||||||
|
|
||||||
const line = d3.line()
|
|
||||||
.x(d => x(d.date))
|
|
||||||
.y(d => y(d.km));
|
|
||||||
|
|
||||||
const svg = d3.select('#container')
|
|
||||||
.append('svg')
|
|
||||||
.attr('width', width + margin.left + margin.right)
|
|
||||||
.attr('height', height + margin.top + margin.bottom)
|
|
||||||
.call(responsivefy)
|
|
||||||
.append('g')
|
|
||||||
.attr('transform', `translate(${margin.left},${margin.top})`);
|
|
||||||
|
|
||||||
svg.append('path')
|
|
||||||
.data([data])
|
|
||||||
.attr('class', 'line')
|
|
||||||
.attr('d', line);
|
|
||||||
|
|
||||||
svg.append('g')
|
|
||||||
.attr('transform', `translate(0,${height})`)
|
|
||||||
.call(d3.axisBottom(x));
|
|
||||||
|
|
||||||
svg.append('g')
|
|
||||||
.call(d3.axisLeft(y));
|
|
||||||
|
|
||||||
|
|
||||||
function responsivefy(svg: any) {
|
function responsivefy(svg: any) {
|
||||||
// container will be the DOM element
|
const container = d3.select(svg.node().parentNode);
|
||||||
// that the svg is appended to
|
const width = parseInt(svg.style('width'), 10);
|
||||||
// we then measure the container
|
const height = parseInt(svg.style('height'), 10);
|
||||||
// and find its aspect ratio
|
const aspect = width / height;
|
||||||
const container = d3.select(svg.node().parentNode),
|
|
||||||
width = parseInt(svg.style('width'), 10),
|
|
||||||
height = parseInt(svg.style('height'), 10),
|
|
||||||
aspect = width / height;
|
|
||||||
|
|
||||||
// set viewBox attribute to the initial size
|
|
||||||
// control scaling with preserveAspectRatio
|
|
||||||
// resize svg on inital page load
|
|
||||||
svg.attr('viewBox', `0 0 ${width} ${height}`)
|
svg.attr('viewBox', `0 0 ${width} ${height}`)
|
||||||
.attr('preserveAspectRatio', 'xMinYMid')
|
.attr('preserveAspectRatio', 'xMinYMid')
|
||||||
.call(resize);
|
.call(resize);
|
||||||
|
|
||||||
// add a listener so the chart will be resized
|
|
||||||
// when the window resizes
|
|
||||||
// multiple listeners for the same event type
|
|
||||||
// requires a namespace, i.e., 'click.foo'
|
|
||||||
// api docs: https://goo.gl/F3ZCFr
|
|
||||||
d3.select(window).on(
|
d3.select(window).on(
|
||||||
'resize.' + container.attr('id'),
|
'resize.' + container.attr('id'),
|
||||||
resize
|
resize
|
||||||
);
|
);
|
||||||
|
|
||||||
// this is the code that resizes the chart
|
|
||||||
// it will be called on load
|
|
||||||
// and in response to window resizes
|
|
||||||
// gets the width of the container
|
|
||||||
// and resizes the svg to fill it
|
|
||||||
// while maintaining a consistent aspect ratio
|
|
||||||
function resize() {
|
function resize() {
|
||||||
const w = parseInt(container.style('width'));
|
const w = parseInt(container.style('width'));
|
||||||
svg.attr('width', w);
|
svg.attr('width', w);
|
||||||
svg.attr('height', Math.round(w / aspect));
|
svg.attr('height', Math.round(w / aspect));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -43,6 +43,7 @@ const data = [
|
|||||||
{ date: '{{p.date}}', km: {{p.km}} },
|
{ date: '{{p.date}}', km: {{p.km}} },
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
]
|
]
|
||||||
|
sessionStorage.setItem('userStats', JSON.stringify(data));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="/public/logbook.js"></script>
|
<script src="/public/logbook.js"></script>
|
||||||
|
Loading…
Reference in New Issue
Block a user