UNPKG

react-meteo-chart

Version:

pre alpha of meteo chart

316 lines (303 loc) 11.8 kB
import React, { Component } from "react"; import moment from "moment"; import { LineSeries, FlexibleXYPlot, Crosshair, HorizontalGridLines, XAxis, YAxis, VerticalGridLines, DecorativeAxis, FlexibleWidthXYPlot, VerticalRectSeries, DiscreteColorLegend, Borders, ChartLabel, } from "react-vis"; import * as color from "./color-utils"; import { rgbToHex } from "../BasicChart"; function getBufrTranlation(name) { switch (name) { case "DIFFERENTIAL REFLECTIVITY": return "Дифференциальная отражающая способность"; case "DOPPLER MEAN VELOCITY (RADIAL)": return "Средняя допплеровская (радиальная) скорость"; case "ECHO TOPS": return "Верхняя граница радиолокационного отражения"; case "HORIZONTAL REFLECTIVITY": return "Горизонтальная отражательная способность"; case "RADAR RAINFALL INTENSITY": return "Интенсивность дождя по радиоционным данным"; case "TOTAL PRECIPITATION PAST 1 HOUR": return "Сумма осадков за последний час"; case "TOTAL PRECIPITATION PAST 12 HOURS": return "Сумма осадков за последние 12 часов"; case "TOTAL PRECIPITATION PAST 3 HOURS": return "Сумма осадков за последние 3 часа"; case "TOTAL PRECIPITATION PAST 6 HOURS": return "Сумма осадков за последние 6 часов"; case "TOTAL PRECIPITATION PAST 24 HOURS": return "Сумма осадков за последние 24 часа"; case "HAZARDOUS PHENOMENA": return "Карта опасных явлений"; default: return name; } } class MiddleVerticalRectSeries extends VerticalRectSeries { _handleNearestX = function (event) { var _props3 = this.props, onNearestX = _props3.onNearestX, data = _props3.data; var minDistance = -Number.POSITIVE_INFINITY; var value = null; var valueIndex = null; var coordinate = this._getXYCoordinateInContainer(event); var xScaleFn = this._getAttributeFunctor("x"); data.forEach(function (item, i) { var currentCoordinate = xScaleFn(item); var newDistance = coordinate.x - currentCoordinate; if (newDistance <= 0 && newDistance > minDistance) { minDistance = newDistance; value = item; valueIndex = i; } }); if (!value) { return; } onNearestX(value, { innerX: xScaleFn(value), index: valueIndex, event: event.nativeEvent, }); }; } class BufrChart extends Component { state = { cross: null, data: this.props.superArr[0], index: 0, stations: this.props.stations, superArr: this.props.superArr, dataType: this.props.dataType, line: this.props.line, }; render() { const { index, data, stations, line, dataType } = this.state; let haveHeight = this.props.isBufrWithHeight(dataType); let yMeasure = haveHeight ? "м" : color.getMeasureByType(dataType); return ( <> {" "} {data ? ( <div style={{ // border: "1px solid #7d9cb8", height: "85%", backgroundColor: data ? rgbToHex(255, 255, 255, this.props.opacity) : "dada", textAlign: "center", }} > <h5 style={{ margin: 5 }}> {this.state.stations[index] && this.state.stations[index].title} </h5> <h6 style={{ margin: 5 }}> {this.props.getBufrTranlation(this.state.dataType)} </h6> <FlexibleXYPlot // TODO: Заменить на FlexibleWidthPlot и прокидывать сюда высоту окна и высчитывать нужный размер(с учетом заголовка и панели выобра станций), margin={{ left: 65, right: 65, top: 45 }} //ибо этот флекс плот умееет занимать только весь контейнер (поэтому панель с выбором станции выползает за пределы контейнера onMouseLeave={() => { this.setState({ cross: null }); }} // height={} style={{ backgroundColor: rgbToHex(255, 255, 255, this.props.opacity), }} xDomain={[data[0].x0, data.slice(-1)[0].x]} yDomain={[ 0, Math.max.apply( Math, data.map((d) => d.y) ), ]} xType="linear" yType="linear" > <HorizontalGridLines /> <VerticalGridLines /> {(haveHeight || dataType.search(/PRECIPITATION PAST/) !== -1) && ( <YAxis // left={0} tickFormat={(v, indx) => (v >= 0 ? `${v} ${yMeasure}` : "")} /> )} {(haveHeight || dataType.search(/PRECIPITATION PAST/) !== -1) && ( <YAxis orientation="right" tickFormat={(v, indx) => (v >= 0 ? `${v} ${yMeasure}` : "")} /> )} <XAxis tickPadding={20} orientation="top" tickValues={[data[0].x0, data.slice(-1)[0].x]} // tickTotal={2} tickFormat={(v, indx) => { if (indx == 0) return `${line[0].toFixed(3)}`; else return `${line[2].toFixed(3)}`; }} /> <XAxis // tickPadding={15} orientation="top" tickValues={[data[0].x0, data.slice(-1)[0].x]} // tickTotal={2} tickFormat={(v, indx) => { if (indx == 0) return ` ${line[1].toFixed(3)}`; else return ` ${line[3].toFixed(3)}`; }} /> <XAxis // tickPadding={20} tickFormat={(v, indx, arr, total) => { return `${v} км`; }} /> <MiddleVerticalRectSeries getNull={(d) => d.y !== null} data={data} colorType="literal" onNearestX={(value, { index }) => { this.setState({ cross: this.state.data .filter((d) => d.x0 == value.x0) .map((value) => ({ x: (value.x + value.x0) / 2, valu: value.valu, y: value.y, y0: value.y0, isValidValue: value.opacity, measure: value.measure, })), }); }} /> <DiscreteColorLegend style={{ backgroundColor: rgbToHex(255, 255, 255, this.props.opacity), }} items={stations} orientation="horizontal" onItemClick={(e) => this.setState({ data: this.state.superArr[e.index], index: e.index, }) } /> {this.state.cross && ( <Crosshair values={this.state.cross}> <div style={{ background: "rgba(42,61,92, 0.9)", width: "155px", color: "#fff", borderRadius: "4px", padding: "2px 0 2px 8px", fontSize: 11, }} > {this.state.cross.filter((d) => d.valu !== null).length > 0 ? ( this.state.cross.filter( (d) => d.valu !== null && d.isValidValue !== 0 ).length > 0 ? ( this.state.cross .filter( (d) => d.valu !== null && d.isValidValue !== 0 ) .map((d) => ( <React.Fragment> <div style={{ display: "flex", justifyContent: "space-between", }} > {haveHeight && ( <div style={{ alignContent: "left" }}> {d.y0 !== -1 ? `${d.y0} м - ${d.y} м: ` : ""} </div> )} <div style={{ marginRight: "5px" }}> {` ${ d.valu !== null ? `${d.valu.toFixed(2)} ${d.measure}` : "" } `}{" "} </div> </div> </React.Fragment> )) ) : ( <div style={{ display: "flex", justifyContent: "center", alignContent: "center", alignItems: "center", flexDirection: "column", fontSize: "17px", height: "100%", }} > Логическое отсутствие данных </div> ) ) : ( <div style={{ display: "flex", justifyContent: "center", alignContent: "center", alignItems: "center", flexDirection: "column", fontSize: "17px", height: "100%", }} > Нет данных </div> )} </div> </Crosshair> )} </FlexibleXYPlot> </div> ) : ( <div style={{ display: "flex", justifyContent: "center", alignContent: "center", alignItems: "center", flexDirection: "column", fontSize: "17px", height: "100%", }} > Нет данных </div> )} </> ); } } export default BufrChart;