HistoryGraph.js
3.96 KB
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
import React, { PureComponent } from 'react'
import { View, Text, StyleSheet } from 'react-native';
import { Svg, G, Line, Rect } from 'react-native-svg'
import { Text as SvgText } from 'react-native-svg'
import * as d3 from 'd3'
// import Showkg from './ShowKg'
const GRAPH_MARGIN = 20
const GRAPH_BAR_WIDTH = 5
const colors = {
axis: '#E4E4E4',
bars: '#15AD13',
bardefult: '#CED4DA'
}
export default class HistoryGraph extends PureComponent {
constructor(props){
super(props);
this.handleClick = this.handleClick.bind(this);
this.state = {
kg: this.props.data[this.props.data.length - 1].label,
index: this.props.data.length-1
}
}
handleClick = inkg => {
this.setState({kg: inkg});
}
componentDidUpdate(prevProps, prevState){
if (this.props.data !== prevProps.data) {
this.setState({
...this.state,
kg : this.props.data[this.props.data.length - 1].label,
index: this.props.data.length-1
})
} }
render() {
// Dimensions
const SVGHeight = 300
const SVGWidth = 300
const graphHeight = SVGHeight - 2 * GRAPH_MARGIN
const graphWidth = SVGWidth - 2 * GRAPH_MARGIN
const data = this.props.data
// X scale point
const xDomain = data.map(item => item.label)
const xRange = [0, graphWidth]
const x = d3.scalePoint()
.domain(xDomain)
.range(xRange)
.padding(1)
// Y scale linear
const maxValue = d3.max(data, d => d.value)
const topValue = Math.ceil(maxValue / this.props.round) * this.props.round
const yDomain = [0, topValue]
const yRange = [0, graphHeight]
const y = d3.scaleLinear()
.domain(yDomain)
.range(yRange)
// top axis and middle axis
const middleValue = topValue / 2
return (
<View>
<Svg width={SVGWidth} height={SVGHeight}>
<G y={graphHeight + GRAPH_MARGIN}>
{/* Top value label */}
<SvgText
x={graphWidth}
textAnchor="end"
y={y(topValue) * -1 - 5}
fontSize={12}
fill="black"
fillOpacity={0.4}>
{topValue + ' ' + this.props.unit}
</SvgText>
{/* top axis */}
<Line
x1="0"
y1={y(topValue) * -1}
x2={graphWidth}
y2={y(topValue) * -1}
stroke={colors.axis}
strokeDasharray={[3, 3]}
strokeWidth="0.5"
/>
{/* middle axis */}
<Line
x1="0"
y1={y(middleValue) * -1}
x2={graphWidth}
y2={y(middleValue) * -1}
stroke={colors.axis}
strokeDasharray={[3, 3]}
strokeWidth="0.5"
/>
{/* bottom axis */}
<Line
x1="0"
y1="2"
x2={graphWidth}
y2="2"
stroke={colors.axis}
strokeWidth="0.5"
/>
{/* bars */}
{data.map(item => (
<Rect
key={'bar' + item.label}
x={x(item.label) - (GRAPH_BAR_WIDTH / 2)}
y={y(item.value) * -1}
rx={2.5}
width={GRAPH_BAR_WIDTH}
height={y(item.value)}
fill = {this.state.kg == item.label ? colors.bars : colors.bardefult}
onPress={()=>this.handleClick(item.label)}
/>
))}
{/* labels */}
{data.map(item => (
<SvgText
key={'label' + item.label}
fontSize="8"
x={x(item.label)}
y="10"
textAnchor="middle">{item.label}</SvgText>
))}
</G>
</Svg>
<Text>{this.state.kg}</Text>
</View>
)
}
}