Merge branch 'chart-refactoring-part-1' into 'master'
Chart refactoring part 1 See merge request bloodyhealth/drip!254
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
import { View } from 'react-native'
|
||||
|
||||
import AppText from '../app-text'
|
||||
import DripHomeIcon from '../../assets/drip-home-icons'
|
||||
|
||||
import styles from './styles'
|
||||
import { cycleDayColor } from '../../styles'
|
||||
|
||||
import { shared as labels } from '../../i18n/en/labels'
|
||||
|
||||
const ChartLegend = () => {
|
||||
return (
|
||||
<View style={[styles.yAxis, styles.chartLegend]}>
|
||||
<DripHomeIcon
|
||||
name="circle"
|
||||
size={styles.yAxis.width - 7}
|
||||
color={cycleDayColor}
|
||||
/>
|
||||
<AppText style={styles.yAxisLabels.dateLabel}>
|
||||
{labels.date.toLowerCase()}
|
||||
</AppText>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export default ChartLegend
|
||||
+22
-52
@@ -1,31 +1,20 @@
|
||||
import React, { Component } from 'react'
|
||||
import { View, FlatList, ActivityIndicator } from 'react-native'
|
||||
import { LocalDate } from 'js-joda'
|
||||
import { makeYAxisLabels, makeHorizontalGrid } from './y-axis'
|
||||
|
||||
import YAxis from './y-axis'
|
||||
import nfpLines from './nfp-lines'
|
||||
import DayColumn from './day-column'
|
||||
import HorizontalGrid from './horizontal-grid'
|
||||
|
||||
import { getCycleDaysSortedByDate, getAmountOfCycleDays } from '../../db'
|
||||
import styles from './styles'
|
||||
import { cycleDayColor } from '../../styles'
|
||||
import { scaleObservable } from '../../local-storage'
|
||||
import config from '../../config'
|
||||
import AppText from '../app-text'
|
||||
import AppLoadingView from '../app-loading'
|
||||
import { shared as labels } from '../../i18n/en/labels'
|
||||
import DripIcon from '../../assets/drip-icons'
|
||||
import DripHomeIcon from '../../assets/drip-home-icons'
|
||||
import nothingChanged from '../../db/db-unchanged'
|
||||
|
||||
const symptomIcons = {
|
||||
bleeding: <DripIcon size={16} name='drip-icon-bleeding' color={styles.iconShades.bleeding[3]}/>,
|
||||
mucus: <DripIcon size={16} name='drip-icon-mucus' color={styles.iconShades.mucus[4]}/>,
|
||||
cervix: <DripIcon size={16} name='drip-icon-cervix' color={styles.iconShades.cervix[3]}/>,
|
||||
desire: <DripIcon size={16} name='drip-icon-desire' color={styles.iconShades.desire[2]}/>,
|
||||
sex: <DripIcon size={16} name='drip-icon-sex' color={styles.iconShades.sex[2]}/>,
|
||||
pain: <DripIcon size={16} name='drip-icon-pain' color={styles.iconShades.pain[0]}/>,
|
||||
mood: <DripIcon size={16} name='drip-icon-mood' color={styles.iconShades.mood[0]}/>,
|
||||
note: <DripIcon size={16} name='drip-icon-note' color={styles.iconShades.note[0]}/>
|
||||
}
|
||||
import AppLoadingView from '../app-loading'
|
||||
|
||||
import nothingChanged from '../../db/db-unchanged'
|
||||
|
||||
export default class CycleChart extends Component {
|
||||
constructor(props) {
|
||||
@@ -129,49 +118,30 @@ export default class CycleChart extends Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { chartHeight, chartLoaded } = this.state
|
||||
return (
|
||||
<View
|
||||
onLayout={this.onLayout}
|
||||
style={{ flexDirection: 'row', flex: 1 }}
|
||||
>
|
||||
{!this.state.chartLoaded && <AppLoadingView />}
|
||||
{!chartLoaded && <AppLoadingView />}
|
||||
|
||||
{this.state.chartHeight && this.state.chartLoaded &&
|
||||
<View>
|
||||
<View style={[styles.yAxis, {height: this.symptomRowHeight}]}>
|
||||
{this.symptomRowSymptoms.map(symptomName => {
|
||||
return <View
|
||||
style={{ alignItems: 'center', justifyContent: 'center' }}
|
||||
key={symptomName}
|
||||
width={styles.yAxis.width}
|
||||
height={this.symptomRowHeight /
|
||||
this.symptomRowSymptoms.length}
|
||||
>
|
||||
{symptomIcons[symptomName]}
|
||||
</View>
|
||||
})}
|
||||
</View>
|
||||
<View style={[styles.yAxis, {height: this.columnHeight}]}>
|
||||
{makeYAxisLabels(this.columnHeight)}
|
||||
</View>
|
||||
<View style={[styles.yAxis, { alignItems: 'center', justifyContent: 'center' }]}>
|
||||
<DripHomeIcon
|
||||
name="circle"
|
||||
size={styles.yAxis.width - 7}
|
||||
color={cycleDayColor}
|
||||
/>
|
||||
<AppText style={[styles.yAxisLabels.dateLabel]}>
|
||||
{labels.date.toLowerCase()}
|
||||
</AppText>
|
||||
</View>
|
||||
</View>}
|
||||
{chartHeight && chartLoaded && (
|
||||
<YAxis
|
||||
height={this.columnHeight}
|
||||
symptomsToDisplay={this.symptomRowSymptoms}
|
||||
symptomsSectionHeight={this.symptomRowHeight}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
{this.state.chartHeight && this.state.chartLoaded &&
|
||||
makeHorizontalGrid(this.columnHeight, this.symptomRowHeight)
|
||||
{chartHeight && chartLoaded && (
|
||||
<HorizontalGrid
|
||||
height={this.columnHeight}
|
||||
startPosition={this.symptomRowHeight}
|
||||
/>)
|
||||
}
|
||||
|
||||
{this.state.chartHeight &&
|
||||
{chartHeight &&
|
||||
<FlatList
|
||||
horizontal={true}
|
||||
inverted={true}
|
||||
|
||||
@@ -18,8 +18,11 @@ import styles from './styles'
|
||||
import config from '../../config'
|
||||
import cycleModule from '../../lib/cycle'
|
||||
import { getCycleDay } from '../../db'
|
||||
|
||||
import DotAndLine from './dot-and-line'
|
||||
import { normalizeToScale } from './y-axis'
|
||||
import SymptomCell from './symptom-cell'
|
||||
|
||||
import { normalizeToScale } from '../helpers/chart'
|
||||
|
||||
const label = styles.column.label
|
||||
|
||||
@@ -139,41 +142,6 @@ class DayColumn extends Component {
|
||||
return false
|
||||
}
|
||||
|
||||
drawSymptom = (symptom) => {
|
||||
|
||||
const { symptomHeight } = this.props
|
||||
const shouldDrawSymptom = this.data.hasOwnProperty(symptom)
|
||||
const styleParent = [styles.symptomRow, {height: symptomHeight}]
|
||||
|
||||
if (shouldDrawSymptom) {
|
||||
const styleSymptom = styles.iconShades[symptom]
|
||||
const symptomData = this.data[symptom]
|
||||
|
||||
const dataIsComplete = this.isSymptomDataComplete(symptom)
|
||||
const isMucusOrCervix = (symptom === 'mucus') || (symptom === 'cervix')
|
||||
|
||||
const backgroundColor = (isMucusOrCervix && !dataIsComplete) ?
|
||||
'white' : styleSymptom[symptomData]
|
||||
const borderWidth = (isMucusOrCervix && !dataIsComplete) ? 2 : 0
|
||||
const borderColor = styleSymptom[0]
|
||||
const styleChild = [styles.symptomIcon, {
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
borderWidth
|
||||
}]
|
||||
|
||||
return (
|
||||
<View style={styleParent} key={symptom}>
|
||||
<View style={styleChild} />
|
||||
</View>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<View style={styleParent} key={symptom} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const columnElements = []
|
||||
const { dateString,
|
||||
@@ -263,9 +231,21 @@ class DayColumn extends Component {
|
||||
onPress={() => this.onDaySelect(dateString)}
|
||||
activeOpacity={1}
|
||||
>
|
||||
<View>
|
||||
{symptomRowSymptoms.map(symptom => this.drawSymptom(symptom))}
|
||||
</View>
|
||||
|
||||
{ symptomRowSymptoms.map(symptom => {
|
||||
const hasSymptomData = this.data.hasOwnProperty(symptom)
|
||||
return (
|
||||
<SymptomCell
|
||||
key={symptom}
|
||||
symptom={symptom}
|
||||
symptomValue={hasSymptomData && this.data[symptom]}
|
||||
isSymptomDataComplete={
|
||||
hasSymptomData && this.isSymptomDataComplete(symptom)
|
||||
}
|
||||
height={this.props.symptomHeight}
|
||||
/>)
|
||||
}
|
||||
)}
|
||||
|
||||
<Surface width={config.columnWidth} height={columnHeight}>
|
||||
{column}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { View } from 'react-native'
|
||||
|
||||
import { getTickPositions } from '../helpers/chart'
|
||||
|
||||
import styles from './styles'
|
||||
|
||||
const HorizontalGrid = ({ height, startPosition }) => {
|
||||
return getTickPositions(height).map(tick => {
|
||||
return (
|
||||
<View
|
||||
top={startPosition + tick}
|
||||
{...styles.horizontalGrid}
|
||||
key={tick}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
HorizontalGrid.propTypes = {
|
||||
height: PropTypes.number,
|
||||
startPosition: PropTypes.number,
|
||||
}
|
||||
|
||||
export default HorizontalGrid
|
||||
@@ -1,5 +1,5 @@
|
||||
import { getCycleStatusForDay } from '../../lib/sympto-adapter'
|
||||
import { normalizeToScale } from './y-axis'
|
||||
import { normalizeToScale } from '../helpers/chart'
|
||||
|
||||
export default function () {
|
||||
const cycle = {
|
||||
|
||||
+59
-29
@@ -11,6 +11,19 @@ const gridLineWidthVertical = 0.6
|
||||
const gridLineWidthHorizontal = 0.3
|
||||
const numberLabelFontSize = 13
|
||||
|
||||
const redColor = '#c3000d'
|
||||
const violetColor = '#7689a9'
|
||||
const shadesOfViolet = ['#e3e7ed', '#c8cfdc', '#acb8cb', '#91a0ba', violetColor] // light to dark
|
||||
const yellowColor = '#dbb40c'
|
||||
const shadesOfYellow = ['#f0e19d', '#e9d26d', '#e2c33c', yellowColor] // light to dark
|
||||
const magentaColor = '#6f2565'
|
||||
const shadesOfMagenta = ['#a87ca2', '#8b5083', magentaColor] // light to dark
|
||||
const pinkColor = '#9e346c'
|
||||
const shadesOfPink = ['#c485a6', '#b15c89', pinkColor] // light to dark
|
||||
const lightGreenColor = '#bccd67'
|
||||
const orangeColor = '#bc6642'
|
||||
const mintColor = '#6ca299'
|
||||
|
||||
const styles = {
|
||||
curve: {
|
||||
stroke: colorTemperature,
|
||||
@@ -48,39 +61,44 @@ const styles = {
|
||||
width: gridLineWidthVertical,
|
||||
}
|
||||
},
|
||||
symptomIcon: {
|
||||
symptomDot: {
|
||||
width: 12,
|
||||
height: 12,
|
||||
borderRadius: 50,
|
||||
},
|
||||
iconShades: {
|
||||
'bleeding': shadesOfRed,
|
||||
'mucus': [
|
||||
'#e3e7ed',
|
||||
'#c8cfdc',
|
||||
'#acb8cb',
|
||||
'#91a0ba',
|
||||
'#7689a9'
|
||||
],
|
||||
'cervix': [
|
||||
'#f0e19d',
|
||||
'#e9d26d',
|
||||
'#e2c33c',
|
||||
'#dbb40c',
|
||||
],
|
||||
'sex': [
|
||||
'#a87ca2',
|
||||
'#8b5083',
|
||||
'#6f2565',
|
||||
],
|
||||
'desire': [
|
||||
'#c485a6',
|
||||
'#b15c89',
|
||||
'#9e346c',
|
||||
],
|
||||
'pain': ['#bccd67'],
|
||||
'mood': ['#bc6642'],
|
||||
'note': ['#6ca299']
|
||||
iconColors: {
|
||||
'bleeding': {
|
||||
color: redColor,
|
||||
shades: shadesOfRed,
|
||||
},
|
||||
'mucus': {
|
||||
color: violetColor,
|
||||
shades: shadesOfViolet,
|
||||
},
|
||||
'cervix': {
|
||||
color: yellowColor,
|
||||
shades: shadesOfYellow,
|
||||
},
|
||||
'sex': {
|
||||
color: magentaColor,
|
||||
shades: shadesOfMagenta,
|
||||
},
|
||||
'desire': {
|
||||
color: pinkColor,
|
||||
shades: shadesOfPink,
|
||||
},
|
||||
'pain': {
|
||||
color: lightGreenColor,
|
||||
shades: [lightGreenColor],
|
||||
},
|
||||
'mood': {
|
||||
color: orangeColor,
|
||||
shades: [orangeColor],
|
||||
},
|
||||
'note': {
|
||||
color: mintColor,
|
||||
shades: [mintColor],
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
width: 27,
|
||||
@@ -109,6 +127,18 @@ const styles = {
|
||||
fontWeight: '100',
|
||||
}
|
||||
},
|
||||
symptomIcon: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
chartLegend: {
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
boldTick: {
|
||||
fontWeight: 'bold',
|
||||
fontSize: 11,
|
||||
},
|
||||
horizontalGrid: {
|
||||
position:'absolute',
|
||||
borderStyle: 'solid',
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { View } from 'react-native'
|
||||
|
||||
import styles from './styles'
|
||||
|
||||
const SymptomCell = ({
|
||||
height,
|
||||
symptom,
|
||||
symptomValue,
|
||||
isSymptomDataComplete
|
||||
}) => {
|
||||
|
||||
const shouldDrawDot = symptomValue !== false
|
||||
const styleParent = [styles.symptomRow, { height }]
|
||||
let styleChild
|
||||
|
||||
if (shouldDrawDot) {
|
||||
const styleSymptom = styles.iconColors[symptom]
|
||||
const symptomColor = styleSymptom.shades[symptomValue]
|
||||
|
||||
const isMucusOrCervix = (symptom === 'mucus') || (symptom === 'cervix')
|
||||
|
||||
const backgroundColor = (isMucusOrCervix && !isSymptomDataComplete) ?
|
||||
'white' : symptomColor
|
||||
const borderWidth = (isMucusOrCervix && !isSymptomDataComplete) ? 2 : 0
|
||||
const borderColor = symptomColor
|
||||
styleChild = [styles.symptomDot, {
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
borderWidth
|
||||
}]
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={styleParent} key={symptom}>
|
||||
{shouldDrawDot && <View style={styleChild} />}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
SymptomCell.propTypes = {
|
||||
height: PropTypes.number,
|
||||
symptom: PropTypes.string,
|
||||
symptomValue: PropTypes.oneOfType([
|
||||
PropTypes.bool,
|
||||
PropTypes.number,
|
||||
]),
|
||||
isSymptomDataComplete: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default SymptomCell
|
||||
@@ -0,0 +1,26 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { View } from 'react-native'
|
||||
|
||||
import DripIcon from '../../assets/drip-icons'
|
||||
|
||||
import styles from './styles'
|
||||
|
||||
const SymptomIcon = ({ symptom, height }) => {
|
||||
return (
|
||||
<View style={styles.symptomIcon} width={styles.yAxis.width} height={height}>
|
||||
<DripIcon
|
||||
size={16}
|
||||
name={`drip-icon-${symptom}`}
|
||||
color={styles.iconColors[symptom].color}
|
||||
/>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
SymptomIcon.propTypes = {
|
||||
height: PropTypes.number,
|
||||
symptom: PropTypes.string,
|
||||
}
|
||||
|
||||
export default SymptomIcon
|
||||
@@ -0,0 +1,34 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { View } from 'react-native'
|
||||
|
||||
import Tick from './tick'
|
||||
|
||||
import { getTickList } from '../helpers/chart'
|
||||
|
||||
import styles from './styles'
|
||||
|
||||
const TickList = ({ height }) => {
|
||||
return (
|
||||
<View style={[styles.yAxis, { height }]}>{
|
||||
getTickList(height)
|
||||
.map(({ label, position, isBold, shouldShowLabel}) => {
|
||||
return (
|
||||
<Tick
|
||||
key={label}
|
||||
yPosition={position}
|
||||
isBold={isBold}
|
||||
shouldShowLabel={shouldShowLabel}
|
||||
label={label}
|
||||
/>
|
||||
)
|
||||
})
|
||||
}</View>
|
||||
)
|
||||
}
|
||||
|
||||
TickList.propTypes = {
|
||||
height: PropTypes.number,
|
||||
}
|
||||
|
||||
export default TickList
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
import AppText from '../app-text'
|
||||
|
||||
import styles from './styles'
|
||||
|
||||
const Tick = ({ yPosition, isBold, shouldShowLabel, label }) => {
|
||||
// this eyeballing is sadly necessary because RN does not
|
||||
// support percentage values for transforms, which we'd need
|
||||
// to reliably place the label vertically centered to the grid
|
||||
const topPosition = yPosition - 8
|
||||
const style = [
|
||||
styles.yAxisLabels.tempScale,
|
||||
{top: topPosition},
|
||||
isBold && styles.boldTick
|
||||
]
|
||||
|
||||
return <AppText style={style}>{shouldShowLabel && label}</AppText>
|
||||
}
|
||||
|
||||
Tick.propTypes = {
|
||||
yPosition: PropTypes.number,
|
||||
isBold: PropTypes.bool,
|
||||
shouldShowLabel: PropTypes.bool,
|
||||
label: PropTypes.string,
|
||||
}
|
||||
|
||||
export default Tick
|
||||
+29
-67
@@ -1,75 +1,37 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { View } from 'react-native'
|
||||
import config from '../../config'
|
||||
|
||||
import SymptomIcon from './symptom-icon'
|
||||
import TickList from './tick-list'
|
||||
import ChartLegend from './chart-legend'
|
||||
|
||||
import styles from './styles'
|
||||
import { scaleObservable, unitObservable } from '../../local-storage'
|
||||
import AppText from '../app-text'
|
||||
|
||||
export function makeYAxisLabels(columnHeight) {
|
||||
const units = unitObservable.value
|
||||
const scaleMax = scaleObservable.value.max
|
||||
const style = styles.yAxisLabels.tempScale
|
||||
|
||||
return getTickPositions(columnHeight).map((y, i) => {
|
||||
const tick = scaleMax - i * units
|
||||
const tickLabel = tick * 10 % 10 ? tick.toString() : tick.toString() + '.0'
|
||||
let showTick
|
||||
let tickBold
|
||||
if (units === 0.1) {
|
||||
showTick = (tick * 10 % 2) ? false : true
|
||||
tickBold = tick * 10 % 5 ? {} : {fontWeight: 'bold', fontSize: 11}
|
||||
} else {
|
||||
showTick = (tick * 10 % 5) ? false : true
|
||||
tickBold = tick * 10 % 10 ? {} : {fontWeight: 'bold', fontSize: 11}
|
||||
}
|
||||
// this eyeballing is sadly necessary because RN does not
|
||||
// support percentage values for transforms, which we'd need
|
||||
// to reliably place the label vertically centered to the grid
|
||||
return (
|
||||
<AppText
|
||||
style={[style, {top: y - 8}, tickBold]}
|
||||
key={i}>
|
||||
{showTick && tickLabel}
|
||||
</AppText>
|
||||
)
|
||||
})
|
||||
const YAxis = ({ height, symptomsToDisplay, symptomsSectionHeight }) => {
|
||||
const symptomIconHeight = symptomsSectionHeight / symptomsToDisplay.length
|
||||
return (
|
||||
<View>
|
||||
<View style={[styles.yAxis, {height: symptomsSectionHeight}]}>
|
||||
{symptomsToDisplay.map(symptom => (
|
||||
<SymptomIcon
|
||||
key={symptom}
|
||||
symptom={symptom}
|
||||
height={symptomIconHeight}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
</View>
|
||||
<TickList height={height} />
|
||||
<ChartLegend />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
export function makeHorizontalGrid(columnHeight, symptomRowHeight) {
|
||||
return getTickPositions(columnHeight).map(tick => {
|
||||
return (
|
||||
<View
|
||||
top={tick + symptomRowHeight}
|
||||
{...styles.horizontalGrid}
|
||||
key={tick}
|
||||
/>
|
||||
)
|
||||
})
|
||||
YAxis.propTypes = {
|
||||
height: PropTypes.number,
|
||||
symptomsToDisplay: PropTypes.array,
|
||||
symptomsSectionHeight: PropTypes.number,
|
||||
}
|
||||
|
||||
function getTickPositions(columnHeight) {
|
||||
const units = unitObservable.value
|
||||
const scaleMin = scaleObservable.value.min
|
||||
const scaleMax = scaleObservable.value.max
|
||||
const numberOfTicks = (scaleMax - scaleMin) * (1 / units) + 1
|
||||
const tickDistance = 1 / (numberOfTicks - 1)
|
||||
const tickPositions = []
|
||||
for (let i = 0; i < numberOfTicks; i++) {
|
||||
const position = getAbsoluteValue(tickDistance * i, columnHeight)
|
||||
tickPositions.push(position)
|
||||
}
|
||||
return tickPositions
|
||||
}
|
||||
|
||||
export function normalizeToScale(temp, columnHeight) {
|
||||
const scale = scaleObservable.value
|
||||
const valueRelativeToScale = (scale.max - temp) / (scale.max - scale.min)
|
||||
return getAbsoluteValue(valueRelativeToScale, columnHeight)
|
||||
}
|
||||
|
||||
function getAbsoluteValue(relative, columnHeight) {
|
||||
// we add some height to have some breathing room
|
||||
const verticalPadding = columnHeight * config.temperatureScale.verticalPadding
|
||||
const scaleHeight = columnHeight - 2 * verticalPadding
|
||||
return scaleHeight * relative + verticalPadding
|
||||
}
|
||||
export default YAxis
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { scaleObservable, unitObservable } from '../../local-storage'
|
||||
import config from '../../config'
|
||||
|
||||
export function normalizeToScale(temp, columnHeight) {
|
||||
const scale = scaleObservable.value
|
||||
const valueRelativeToScale = (scale.max - temp) / (scale.max - scale.min)
|
||||
return getAbsoluteValue(valueRelativeToScale, columnHeight)
|
||||
}
|
||||
|
||||
function getAbsoluteValue(relative, columnHeight) {
|
||||
// we add some height to have some breathing room
|
||||
const verticalPadding = columnHeight * config.temperatureScale.verticalPadding
|
||||
const scaleHeight = columnHeight - 2 * verticalPadding
|
||||
return scaleHeight * relative + verticalPadding
|
||||
}
|
||||
|
||||
export function getTickPositions(columnHeight) {
|
||||
const units = unitObservable.value
|
||||
const scaleMin = scaleObservable.value.min
|
||||
const scaleMax = scaleObservable.value.max
|
||||
const numberOfTicks = (scaleMax - scaleMin) * (1 / units) + 1
|
||||
const tickDistance = 1 / (numberOfTicks - 1)
|
||||
const tickPositions = []
|
||||
for (let i = 0; i < numberOfTicks; i++) {
|
||||
const position = getAbsoluteValue(tickDistance * i, columnHeight)
|
||||
tickPositions.push(position)
|
||||
}
|
||||
return tickPositions
|
||||
}
|
||||
|
||||
export function getTickList(columnHeight) {
|
||||
|
||||
const units = unitObservable.value
|
||||
const scaleMax = scaleObservable.value.max
|
||||
|
||||
return getTickPositions(columnHeight).map((tickPosition, i) => {
|
||||
|
||||
const tick = scaleMax - i * units
|
||||
let isBold, label, shouldShowLabel
|
||||
|
||||
if (Number.isInteger(tick)) {
|
||||
isBold = true
|
||||
label = tick.toString() + '.0'
|
||||
} else {
|
||||
isBold = false
|
||||
label = tick.toString()
|
||||
}
|
||||
|
||||
// when temp range <= 3, units === 0.1 we show temp values with step 0.2
|
||||
// when temp range > 3, units === 0.5 we show temp values with step 0.5
|
||||
|
||||
if (units === 0.1) {
|
||||
// show label with step 0.2
|
||||
shouldShowLabel = !(tick * 10 % 2)
|
||||
} else {
|
||||
// show label with step 0.5
|
||||
shouldShowLabel = !(tick * 10 % 5)
|
||||
}
|
||||
|
||||
return {
|
||||
position: tickPosition,
|
||||
label,
|
||||
isBold,
|
||||
shouldShowLabel,
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user