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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
import * as React from "react";
import { Doc } from "../../../../fields/Doc";
import { NumCast } from "../../../../fields/Types";
import "./HistogramBox.scss";
interface HistogramBoxProps {
rootDoc: Doc;
pairs: {
x: number,
y: number
}[]
}
export class HistogramBox extends React.Component<HistogramBoxProps> {
private origin = {x: 0.1 * this.width, y: 0.9 * this.height};
@computed get width() {
return NumCast(this.props.rootDoc.width);
}
@computed get height() {
return NumCast(this.props.rootDoc.height);
}
@computed get x() {
return NumCast(this.props.rootDoc.x);
}
@computed get y() {
return NumCast(this.props.rootDoc.y);
}
@computed get generatePoints() {
// evenly distribute points along the x axis
const xVals: number[] = this.props.pairs.map(p => p.x);
const yVals: number[] = this.props.pairs.map(p => p.y);
const xMin = Math.min(...xVals);
const xMax = Math.max(...xVals);
const yMin = Math.min(...yVals);
const yMax = Math.max(...yVals);
const xRange = xMax - xMin;
const yRange = yMax - yMin;
const xScale = this.width / xRange;
const yScale = this.height / yRange;
const xOffset = (this.x + (0.1 * this.width)) - xMin * xScale;
const yOffset = (this.y + (0.25 * this.height)) - yMin * yScale;
const points: {
x: number,
y: number
}[] = this.props.pairs.map(p => {
return {
x: (p.x * xScale + xOffset) + this.origin.x,
y: (p.y * yScale + yOffset)
}
});
return points;
}
@computed get generateGraphLine() {
const points = this.generatePoints;
// loop through points and create a line from each point to the next
let lines: {
x1: number,
y1: number,
x2: number,
y2: number
}[] = [];
for (let i = 0; i < points.length - 1; i++) {
lines.push({
x1: points[i].x,
y1: points[i].y,
x2: points[i + 1].x,
y2: points[i + 1].y
});
}
// generate array of svg with lines
let svgLines: JSX.Element[] = [];
for (let i = 0; i < lines.length; i++) {
svgLines.push(
<line
className="svgLine"
key={i}
x1={lines[i].x1}
y1={lines[i].y1}
x2={lines[i].x2}
y2={lines[i].y2}
stroke="black"
strokeWidth={2}
/>
);
}
let res = [];
for (let i = 0; i < svgLines.length; i++) {
res.push(<svg className="svgContainer">{svgLines[i]}</svg>)
}
return res;
}
@computed get generateAxes() {
const xAxis = {
x1: 0.1 * this.width,
x2: 0.9 * this.width,
y1: 0.9 * this.height,
y2: 0.9 * this.height,
};
const yAxis = {
x1: 0.1 * this.width,
x2: 0.1 * this.width,
y1: 0.25 * this.height,
y2: 0.9 * this.height,
};
return (
[
(<svg className="svgContainer">
{/* <line className="svgLine" x1={yAxis} y1={xAxis} x2={this.width - (0.1 * this.width)} y2={xAxis} /> */}
<line className="svgLine" x1={xAxis.x1} y1={xAxis.y1} x2={xAxis.x2} y2={xAxis.y2}/>
{/* <line className="svgLine" x1={yAxis} y1={xAxis} x2={yAxis} y2={this.y + 50} /> */}
</svg>),
(
<svg className="svgContainer">
<line className="svgLine" x1={yAxis.x1} y1={yAxis.y1} x2={yAxis.x2} y2={yAxis.y2} />
{/* <line className="svgLine" x1={yAxis} y1={xAxis} x2={yAxis} y2={this.y + 50} /> */}
</svg>)
]
)
}
render() {
return (
<div>histogram box
{/* <svg className="svgContainer">
{this.generateSVGLine}
</svg> */}
{this.generateAxes[0]}
{this.generateAxes[1]}
{this.generateGraphLine.map(line => line)}
</div>
)
}
}
|