aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/DataVizBox/utils/D3Utils.ts
blob: ffc859c92c635b9f7916715d277ee4f373c68489 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import * as d3 from 'd3';

export interface DataPoint {
    x: number;
    y: number;
}
// TODO: nda - implement function that can handle range for strings

export const minMaxRange = (dataPts: DataPoint[][]) => {
    // find the max and min of all the data points
    const yMin = d3.min(dataPts, d => d3.min(d, m => Number(m.y)));
    const yMax = d3.max(dataPts, d => d3.max(d, m => Number(m.y)));

    const xMin = d3.min(dataPts, d => d3.min(d, m => Number(m.x)));
    const xMax = d3.max(dataPts, d => d3.max(d, m => Number(m.x)));

    return { xMin, xMax, yMin, yMax };
};

export const scaleCreatorCategorical = (labels: string[], range: number[]) => {
    const scale = d3.scaleBand().domain(labels).range(range);

    return scale;
};

export const scaleCreatorNumerical = (domA: number, domB: number, rangeA: number, rangeB: number) => d3.scaleLinear().domain([domA, domB]).range([rangeA, rangeB]);

export const createLineGenerator = (xScale: d3.ScaleLinear<number, number, never>, yScale: d3.ScaleLinear<number, number, never>) =>
    // TODO: nda - look into the different types of curves
    d3
        .line<DataPoint>()
        .x(d => xScale(d.x))
        .y(d => yScale(d.y))
        .curve(d3.curveMonotoneX);

export const xAxisCreator = (g: d3.Selection<SVGGElement, unknown, null, undefined>, height: number, xScale: d3.ScaleLinear<number, number, never>) => {
    g.attr('class', 'x-axis').attr('transform', `translate(0,${height})`).call(d3.axisBottom(xScale).tickSize(15));
};

export const yAxisCreator = (g: d3.Selection<SVGGElement, unknown, null, undefined>, marginLeft: number, yScale: d3.ScaleLinear<number, number, never>) => {
    g.attr('class', 'y-axis').call(d3.axisLeft(yScale));
};

export const xGrid = (g: d3.Selection<SVGGElement, unknown, null, undefined>, height: number, scale: d3.ScaleLinear<number, number, never>) => {
    g.attr('class', 'xGrid')
        .attr('transform', `translate(0,${height})`)
        .call(
            d3
                .axisBottom(scale)
                .tickSize(-height)
                .tickFormat((/* a, b */) => '')
        );
};

export const yGrid = (g: d3.Selection<SVGGElement, unknown, null, undefined>, width: number, scale: d3.ScaleLinear<number, number, never>) => {
    g.attr('class', 'yGrid').call(
        d3
            .axisLeft(scale)
            .tickSize(-width)
            .tickFormat((/* a, b */) => '')
    );
};

export const drawLine = (p: d3.Selection<SVGPathElement, unknown, null, undefined>, dataPts: DataPoint[], lineGen: d3.Line<DataPoint>, extra: boolean) => {
    p.datum(dataPts)
        .attr('fill', 'none')
        .attr('stroke', 'rgba(53, 162, 235, 0.5)')
        .attr('stroke-width', 2)
        .attr('stroke', extra ? 'blue' : 'black')
        .attr('class', 'line')
        .attr('d', lineGen);
};