react-meteo-chart
Version:
pre alpha of meteo chart
316 lines (303 loc) • 11.8 kB
JSX
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;