diff --git a/src/main/weather/charts/HourlyChartService.js b/src/main/weather/charts/HourlyChartService.js index d83cdf1..3a9dc46 100644 --- a/src/main/weather/charts/HourlyChartService.js +++ b/src/main/weather/charts/HourlyChartService.js @@ -7,19 +7,28 @@ import UvIndexChart from "./uvindex/UvIndexChart"; function HourlyTemperatureChart(props){ let i = 0; return parseHourlyForecast(props.hourlyForecast).map(hourlyForecastPerDay => - ) + ) } function HourlyRainfallChart(props){ let i = 0; return parseHourlyForecast(props.hourlyForecast).map(hourlyForecastPerDay => - ) + ) } function HourlyUvIndexChart(props){ let i = 0; return parseHourlyForecast(props.hourlyForecast).map(hourlyForecastPerDay => - ) + ) } //todo mb keep this in state instead of 'hourlyForecast' @@ -43,6 +52,15 @@ function parseHourlyForecast(hourlyForecast) { return hourlyForecastByDailyDate; } +function getDimensions(elementLength, graphHeight=70) { + return { + svgWidth: 80 * elementLength, + svgHeight: 240, + graphHeight: graphHeight, + initialYCordOfChart: 60, + } +} + export { HourlyTemperatureChart, HourlyRainfallChart, diff --git a/src/main/weather/charts/rainfall/RainfallChart.js b/src/main/weather/charts/rainfall/RainfallChart.js index 2ec7ba5..f9115bc 100644 --- a/src/main/weather/charts/rainfall/RainfallChart.js +++ b/src/main/weather/charts/rainfall/RainfallChart.js @@ -5,15 +5,6 @@ import IMAGES from "../../../../resource/ImagePath"; import mapDataToIcon from "../common/ForecastIconMapper"; -let SVG_WIDTH = 600; -const SVG_HEIGHT = 240; -const GRAPH_HEIGHT = 70; -const START_Y_POSITION_OF_GRAPH = 60; -const GRAPH_TRANSFORMATION = -1; - -const DEGREE_SIGN = '°'; -const GRADIENT_ID = 'grad'; - const COLORS = { mainText: '#111', pathBlue: '#5BC3CE', @@ -21,49 +12,47 @@ const COLORS = { gradientLight: '#FFF' }; - class RainfallChart extends React.PureComponent { - render() { - SVG_WIDTH = 80 * this.props.data.length; + render = () => { const data = this.props.data; const minValue = d3.min(data, d => d.precipIntensity); const maxValue = d3.max(data, d => d.precipIntensity); console.log(data); - const xFunction = this.getFunctionX(data); - const yFunction = this.getFunctionY(minValue, maxValue); + const xFunction = this.getFunctionX(data, this.props.dimensions.svgWidth); + const yFunction = this.getFunctionY(minValue, maxValue, this.props.dimensions.graphHeight, this.props.dimensions.initialYCordOfChart); return ( - - + + {/* grid lines */} - {this.generateVerticalBeginLine()} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT)} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT / 2, 50)} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH)} - {this.generateVerticalGridLines(data, xFunction)} + {this.generateVerticalBeginLine(this.props.dimensions.svgHeight)} + {this.generateFullLengthLine(-this.props.dimensions.initialYCordOfChart - this.props.dimensions.graphHeight, this.props.dimensions.svgWidth)} + {this.generateFullLengthLine(-this.props.dimensions.initialYCordOfChart - this.props.dimensions.graphHeight / 2, this.props.dimensions.svgWidth, 50)} + {this.generateFullLengthLine(-this.props.dimensions.initialYCordOfChart, this.props.dimensions.svgWidth)} + {this.generateVerticalGridLines(data, xFunction, this.props.dimensions.graphHeight, this.props.dimensions.initialYCordOfChart)} {/* day date text */} - {this.generateDateText(data)} + {this.generateDateText(data, this.props.dimensions.svgHeight)} {/* forecast images*/} - {this.generateForecastImageForEach(data, xFunction)} + {this.generateForecastImageForEach(data, xFunction, this.props.dimensions.graphHeight, this.props.dimensions.initialYCordOfChart)} {this.generateRainfallImageForEach(data, xFunction)} {/* data values ( text for: hour, temperature, rainfall % ) */} {this.generateDegreeTextForEachItem(data, xFunction, yFunction)} {this.generateTextForEachItem(data, 'precipProbability', xFunction, 8, -20, 14)} - {this.generateTextForEachItem(data, 'time', xFunction, 0, (START_Y_POSITION_OF_GRAPH + GRAPH_HEIGHT) * GRAPH_TRANSFORMATION - 70, 20)} + {this.generateTextForEachItem(data, 'time', xFunction, 0, (this.props.dimensions.initialYCordOfChart + this.props.dimensions.graphHeight) * -1 - 70, 20)} ); - } + }; - getFunctionX(data) { + getFunctionX(data, svgWidth) { const xDomain = data.map(item => item.time); - const xRange = [0, SVG_WIDTH]; + const xRange = [0, svgWidth]; return d3 .scalePoint() .domain(xDomain) @@ -71,32 +60,32 @@ class RainfallChart extends React.PureComponent { .padding(1); } - getFunctionY(minValue, maxValue) { + getFunctionY(minValue, maxValue, graphHeight, initialYCordOfChart) { const yDomain = [minValue, maxValue]; - const yRange = [START_Y_POSITION_OF_GRAPH, START_Y_POSITION_OF_GRAPH + GRAPH_HEIGHT]; + const yRange = [initialYCordOfChart, initialYCordOfChart + graphHeight]; return d3 .scaleLinear() .domain(yDomain) .range(yRange); } - generateVerticalBeginLine() { + generateVerticalBeginLine(svgHeight) { return ; } - generateFullLengthLine(y, xPadding = 0) { + generateFullLengthLine(y, svgWidth, xPadding = 0 ) { return ; } - generateVerticalGridLines(data, x) { + generateVerticalGridLines(data, x, graphHeight, initialYCordOfChart) { return (data.map(item => ( ( diff --git a/src/main/weather/charts/temperature/TemperatureChart.js b/src/main/weather/charts/temperature/TemperatureChart.js index 4ea9457..9503d21 100644 --- a/src/main/weather/charts/temperature/TemperatureChart.js +++ b/src/main/weather/charts/temperature/TemperatureChart.js @@ -5,12 +5,6 @@ import IMAGES from "../../../../resource/ImagePath"; import mapDataToIcon from "../common/ForecastIconMapper"; -let SVG_WIDTH = 600; -const SVG_HEIGHT = 240; -const GRAPH_HEIGHT = 70; -const START_Y_POSITION_OF_GRAPH = 60; -const GRAPH_TRANSFORMATION = -1; - const DEGREE_SIGN = '°'; const GRADIENT_ID = 'grad'; @@ -24,53 +18,51 @@ const COLORS = { class TemperatureChart extends React.PureComponent { - render() { - SVG_WIDTH = 80 * this.props.data.length; - + render = () => { const data = this.props.data; const minValue = d3.min(data, d => d.temperature); const maxValue = d3.max(data, d => d.temperature); - const xFunction = this.getFunctionX(data); - const yFunction = this.getFunctionY(minValue, maxValue); + const xFunction = this.getFunctionX(data, this.props.dimensions.svgWidth); + const yFunction = this.getFunctionY(minValue, maxValue, this.props.dimensions.graphHeight, this.props.dimensions.initialYCordOfChart); return ( - - + + {this.getDefinitions()} {/* grid lines */} - {this.generateVerticalBeginLine()} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT)} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT / 2, 50)} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH)} - {this.generateVerticalGridLines(data, xFunction)} + {this.generateVerticalBeginLine(this.props.dimensions.svgHeight)} + {this.generateFullLengthLine(-this.props.dimensions.initialYCordOfChart - this.props.dimensions.graphHeight, this.props.dimensions.svgWidth)} + {this.generateFullLengthLine(-this.props.dimensions.initialYCordOfChart - this.props.dimensions.graphHeight / 2, this.props.dimensions.svgWidth,50)} + {this.generateFullLengthLine(-this.props.dimensions.initialYCordOfChart, this.props.dimensions.svgWidth)} + {this.generateVerticalGridLines(data, xFunction, this.props.dimensions.graphHeight, this.props.dimensions.initialYCordOfChart)} {/* min & max values and data text*/} - {this.generateSingleText('MAX ' + maxValue + DEGREE_SIGN, 13, -START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT - 2)} - {this.generateSingleText('MIN ' + minValue + DEGREE_SIGN, 13, -START_Y_POSITION_OF_GRAPH - 2)} - {this.generateDateText(data)} + {this.generateSingleText('MAX ' + maxValue + DEGREE_SIGN, 13, -this.props.dimensions.initialYCordOfChart - this.props.dimensions.graphHeight - 2)} + {this.generateSingleText('MIN ' + minValue + DEGREE_SIGN, 13, -this.props.dimensions.initialYCordOfChart - 2)} + {this.generateDateText(data, this.props.dimensions.svgHeight)} {/* forecast images*/} - {this.generateForecastImageForEach(data, xFunction)} + {this.generateForecastImageForEach(data, xFunction, this.props.dimensions.graphHeight, this.props.dimensions.initialYCordOfChart)} {this.generateRainfallImageForEach(data, xFunction)} {/* temperature path */} - {this.generateGradientComponent(data, xFunction, yFunction)} + {this.generateGradientComponent(data, xFunction, yFunction, this.props.dimensions.initialYCordOfChart)} {this.generateLineComponents(data, xFunction, yFunction)} {this.generateDotForEach(data, xFunction, yFunction)} {/* data values ( text for: hour, temperature, rainfall % ) */} {this.generateDegreeTextForEachItem(data, xFunction, yFunction)} {this.generateTextForEachItem(data, 'precipProbability', xFunction, 8, -20, 14)} - {this.generateTextForEachItem(data, 'time', xFunction, 0, SVG_HEIGHT*-1 + 40, 20)} + {this.generateTextForEachItem(data, 'time', xFunction, 0, this.props.dimensions.svgHeight*-1 + 40, 20)} ); - } + }; - getFunctionX(data) { + getFunctionX(data, svgWidth) { const xDomain = data.map(item => item.time); - const xRange = [0, SVG_WIDTH]; + const xRange = [0, svgWidth]; return d3 .scalePoint() .domain(xDomain) @@ -78,9 +70,9 @@ class TemperatureChart extends React.PureComponent { .padding(1); } - getFunctionY(minValue, maxValue) { + getFunctionY(minValue, maxValue, graphHeight, initialYCordOfChart) { const yDomain = [minValue, maxValue]; - const yRange = [START_Y_POSITION_OF_GRAPH, START_Y_POSITION_OF_GRAPH + GRAPH_HEIGHT]; + const yRange = [initialYCordOfChart, initialYCordOfChart + graphHeight]; return d3 .scaleLinear() .domain(yDomain) @@ -96,23 +88,23 @@ class TemperatureChart extends React.PureComponent { ; } - generateVerticalBeginLine() { + generateVerticalBeginLine(svgHeight) { return ; } - generateFullLengthLine(y, xPadding = 0) { + generateFullLengthLine(y, svgWidth, xPadding = 0) { return ; } - generateVerticalGridLines(data, x) { + generateVerticalGridLines(data, x, graphHeight, initialYCordOfChart) { return (data.map(item => ( ( @@ -207,7 +199,7 @@ class TemperatureChart extends React.PureComponent { @@ -226,11 +218,11 @@ class TemperatureChart extends React.PureComponent { ; } - generateDateText(data) { + generateDateText(data, svgHeight) { return diff --git a/src/main/weather/charts/uvindex/UvIndexChart.js b/src/main/weather/charts/uvindex/UvIndexChart.js index 0e268bd..ef03d61 100644 --- a/src/main/weather/charts/uvindex/UvIndexChart.js +++ b/src/main/weather/charts/uvindex/UvIndexChart.js @@ -4,56 +4,53 @@ import * as d3 from 'd3'; import UV_COLORS from './UvColors'; -let SVG_WIDTH = 600; -const SVG_HEIGHT = 240; -const GRAPH_HEIGHT = 100; -const START_Y_POSITION_OF_GRAPH = 60; - const COLORS = { mainText: '#111', gridColor: 'rgba(81,81,81,0.3)', }; - class UvIndexChart extends React.PureComponent { render() { - SVG_WIDTH = 80 * this.props.data.length; - const data = this.props.data; + const svgWidth = this.props.dimensions.svgWidth; + const svgHeight = this.props.dimensions.svgHeight; + const graphHeight = this.props.dimensions.graphHeight; + const initialYCordOfChart = this.props.dimensions.initialYCordOfChart; + const minValue = d3.min(data, d => d.uvIndex); const maxValue = d3.max(data, d => d.uvIndex); - const xFunction = this.getFunctionX(data); - const yFunction = this.getFunctionY(minValue, maxValue); + const xFunction = this.getFunctionX(data, svgWidth); + const yFunction = this.getFunctionY(minValue, maxValue, graphHeight, initialYCordOfChart); return ( - - + + {/* grid lines */} - {this.generateVerticalBeginLine()} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT)} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH - GRAPH_HEIGHT / 2, 50)} - {this.generateFullLengthLine(-START_Y_POSITION_OF_GRAPH)} - {this.generateVerticalGridLines(data, xFunction)} + {this.generateVerticalBeginLine(svgHeight)} + {this.generateFullLengthLine(-initialYCordOfChart - graphHeight, svgWidth)} + {this.generateFullLengthLine(-initialYCordOfChart - graphHeight / 2, svgWidth, 50)} + {this.generateFullLengthLine(-initialYCordOfChart, svgWidth)} + {this.generateVerticalGridLines(data, xFunction, graphHeight, initialYCordOfChart)} {/* day date (day name) text */} - {this.generateDateText(data)} + {this.generateDateText(data, svgHeight)} {/* data bars */} - {this.generateDataBars(data, xFunction, yFunction, maxValue)} + {this.generateDataBars(data, xFunction, yFunction, maxValue, initialYCordOfChart)} {/* data values ( text for: hour, temperature, rainfall % ) */} {this.generateTextForEachItem(data, 'uvIndex', xFunction, 0, -20, 14)} - {this.generateTextForEachItem(data, 'time', xFunction, 0, SVG_HEIGHT*-1 + 40, 20)} + {this.generateTextForEachItem(data, 'time', xFunction, 0, svgHeight*-1 + 40, 20)} ); } - getFunctionX(data) { + getFunctionX(data, svgWidth) { const xDomain = data.map(item => item.time); - const xRange = [0, SVG_WIDTH]; + const xRange = [0, svgWidth]; return d3 .scalePoint() .domain(xDomain) @@ -61,32 +58,32 @@ class UvIndexChart extends React.PureComponent { .padding(1); } - getFunctionY(minValue, maxValue) { + getFunctionY(minValue, maxValue, graphHeight, initialYCordOfChart) { const yDomain = [minValue, maxValue]; - const yRange = [START_Y_POSITION_OF_GRAPH, START_Y_POSITION_OF_GRAPH + GRAPH_HEIGHT]; + const yRange = [initialYCordOfChart, initialYCordOfChart + graphHeight]; return d3 .scaleLinear() .domain(yDomain) .range(yRange); } - generateVerticalBeginLine() { + generateVerticalBeginLine(svgHeight) { return ; } - generateFullLengthLine(y, xPadding = 0) { + generateFullLengthLine(y, svgWidth, xPadding = 0) { return ; } - generateVerticalGridLines(data, x) { + generateVerticalGridLines(data, x, graphHeight, initialYCordOfChart) { return (data.map(item => ( ( @@ -138,11 +135,11 @@ class UvIndexChart extends React.PureComponent { return UV_COLORS.uvExtreme; } - generateDateText(data) { + generateDateText(data, svgHeight) { return