left: data, top: toolbar, right, bottom: graphs
change x,y function
change color
hide data
hide tool bar
add cursor to multiple plots
--src
--app.js
--app.cs
--colorSelect.js
--mathSelect.js
--mathPlot.js
package.json
{
"name": "react-chart",
"version": "0.1.0",
"private": true,
"dependencies": {
"@material-ui/core": "^1.3.1",
"@material-ui/icons": "^1.1.0",
"bootstrap": "^4.1.1",
"react": "^16.4.1",
"react-dom": "^16.4.1",
"react-scripts": "1.1.4",
"react-vis": "^1.10.1"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
-----------------------------------------------------
app.js
import React, { Component } from 'react';
import './App.css';
import '../node_modules/react-vis/dist/style.css';
import {
XYPlot, LineSeries, VerticalGridLines, HorizontalGridLines,
XAxis, YAxis, VerticalBarSeries, MarkSeries, AreaSeries,
Crosshair,
} from 'react-vis';
import Grid from '@material-ui/core/Grid';
import Button from '@material-ui/core/Button';
import Switch from '@material-ui/core/Switch';
import MathSelect from './mathSelect';
import ColorSelect from './colorSelect';
import { withStyles } from '@material-ui/core/styles';
import generateData from './mathPlot';
import Menu from '@material-ui/icons/Menu';
import blue from '@material-ui/core/colors/blue';
const styles = theme => ({
button: {
margin: 0.5 * theme.spacing.unit,
},
blue: {
color: blue[500],
backgroundColor: blue[100],
},
});
class App extends Component {
constructor(props) {
super(props);
this.state = {
data: [
{ x: 0, y: 0 },
{ x: 0.5, y: 0.5 },
{ x: 1, y: 1 },
{ x: 1.5, y: 1.5 },
{ x: 2, y: 2 },
{ x: 2.5, y: 2.5 },
{ x: 3, y: 3 },
{ x: 3.5, y: 3.5 },
{ x: 4, y: 4 },
{ x: 4.5, y: 4.5 },
{ x: 5, y: 5 },
{ x: 5.5, y: 5.5 },
{ x: 6, y: 6 },
{ x: 6.5, y: 6.5 },
{ x: 7, y: 7 },
{ x: 7.5, y: 7.5 },
{ x: 8, y: 8 },
{ x: 8.5, y: 8.5 },
{ x: 9, y: 9 },
{ x: 9.5, y: 9.5 },
{ x: 10, y: 10 },
],
dataOpen: true,
xType: 1,
yType: 1,
headerCollapse: false,
colorCode: "#12939A",
crosshairValues: [],
};
}
handleClick_open() {
this.setState(prevState => {
return { dataOpen: !prevState.dataOpen };
})
}
handleChange_switch = name => e => {
this.setState({ [name]: e.target.checked });
}
handleChange_x(type) {
const newX = generateData(type);
const newData = this.state.data.map(
(item, index) => {
return { x: newX[index], y: item.y };
}
);
this.setState({
data: newData,
xType: type,
});
}
handleChange_y(type) {
const newY = generateData(type);
const newData = this.state.data.map(
(item, index) => {
return { x: item.x, y: newY[index] };
}
);
this.setState({
data: newData,
yType: type,
});
}
handleClick_collapse() {
this.setState(prevState => {
return { headerCollapse: !prevState.headerCollapse };
})
}
handleChange_color(code) {
this.setState({ colorCode: code });
}
render() {
const { classes } = this.props;
const dataClass = this.state.dataOpen ? "colume-25" : "colume-0";
const chartClass = this.state.dataOpen ? "colume-75" : "colume-100";
const headerClass = this.state.headerCollapse ? "sticky-header-collapse" : "sticky-header";
const headerMenu =
<div className={headerClass}>
<Switch
checked={this.state.dataOpen}
onChange={this.handleChange_switch('dataOpen')}
value="dataOpen"
/>
<Button variant="contained" size="small"
className={classes.button}
onClick={() => this.handleClick_open()}>
{this.state.dataOpen ? "hide data" : "show data"}
</Button>
<MathSelect type={this.state.xType} label="X:"
callBack={(value) => this.handleChange_x(value)} />
<MathSelect type={this.state.yType} label="Y:"
callBack={(value) => this.handleChange_y(value)} />
<ColorSelect colorCode={this.state.colorCode} label="Color:"
callBack={(colorCode) => this.handleChange_color(colorCode)} />
</div>
const graphPlots = <div className="graph-content">
<Grid container spacing={24}>
{/* ------------line series------------------- */}
<Grid item xs={12} sm={6}>
<h4 className="text-center">Line series</h4>
<XYPlot height={250} width={250} stroke={this.state.colorCode}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis title="time (S)" />
<YAxis title="velocity (M/S)" />
<LineSeries data={this.state.data} />
</XYPlot>
</Grid>
{/* ------------bar series------------------- */}
<Grid item xs={12} sm={6}>
<h4 className="text-center">Bar series</h4>
<XYPlot height={250} width={250} color={this.state.colorCode}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis />
<YAxis />
<VerticalBarSeries data={this.state.data} />
</XYPlot>
</Grid>
{/* ------------mark series------------------- */}
<Grid item xs={12} sm={6}>
<h4 className="text-center">Mark series</h4>
<XYPlot height={250} width={250} color={this.state.colorCode}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis />
<YAxis />
<MarkSeries data={this.state.data} />
</XYPlot>
</Grid>
{/* ------------area series------------------- */}
<Grid item xs={12} sm={6}>
<h4 className="text-center">Area series</h4>
<XYPlot height={250} width={250} stroke={this.state.colorCode}
fill={this.state.colorCode}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis />
<YAxis />
<AreaSeries data={this.state.data} />
</XYPlot>
</Grid>
</Grid>
</div>
const mixData = [generateData(6), generateData(7), generateData(8)];
const mixPlots =
<Grid container spacing={24}>
{/* ------------mix series------------------- */}
< Grid item xs={12} sm={12}>
<h4 className="text-center">Multi series</h4>
<XYPlot height={250} width={800}
onMouseLeave={() => this.setState({ crosshairValues: [] })}>
<VerticalGridLines />
<HorizontalGridLines />
<XAxis title="time" tickValues={generateData(1)} />
<YAxis title="velocity" />
<LineSeries data={generateData(6)} stroke="#12939A"
onNearestX={(value, { index }) =>
this.setState({ crosshairValues: mixData.map(d => d[index]) })} />
<MarkSeries data={generateData(7)} color="#1A3177" />
<AreaSeries data={generateData(8)}
stroke="#FF9833" fill="#FF9833" />
<Crosshair values={this.state.crosshairValues}/>
</XYPlot>
</Grid >
</Grid>
const collapseIconButton =
<div className="collapse-iconButton">
<Button variant="fab" mini className={classes.blue}
onClick={() => this.handleClick_collapse()}>
<Menu />
</Button>
</div>
return (
<div>
<div className="row-">
{/* ------------data------------------- */}
<div className={dataClass}>
{this.state.data.map((item, index) =>
(<div key={index}>
<p> x{index}= {item.x.toFixed(2)},
y{index}={item.y.toFixed(2)}</p>
</div>
))}
</div>
{/* ------------chart------------------- */}
<div className={chartClass}>
{headerMenu}
{collapseIconButton}
{graphPlots}
</div>
</div>
{mixPlots}
</div>
);
}
}
export default withStyles(styles)(App);
-----------------------------------------------
app.css
.row-{
display:flex;
}
.colume-50{
flex:50%;
}
.colume-25 {
display:block;
flex: 25%;
}
.colume-75 {
flex: 75%;
}
.colume-0 {
display:none;
flex: 0;
}
.colume-100 {
flex: 100%;
}
.text-center{
text-align:center;
}
.sticky-header {
position: fixed;
top: 0;
z-index: 2;
background-color: aliceblue;
transition: top 1s;
}
.sticky-header-collapse {
position: fixed;
top: -80px;
z-index: 2;
background-color: aliceblue;
transition: top 1s
}
.graph-content{
margin-top:50px;
}
.collapse-iconButton {
position: fixed;
top: 0;
right: 0;
z-index: 2;
}
-------------------------------------------
mathPlot.js
const generateLinear = () => {
const linearArray = [];
let i = 0;
for (; i <= 10; i+=0.5) {
linearArray.push(
i
)
}
return linearArray;
}
const generateLogrithmic = () => {
const logArray = [0,0];
let i = 1;
for (; i <= 10; i+=0.5) {
logArray.push(
Math.log(i) / Math.log(10) * 10
)
}
return logArray;
}
const generateExponential = () => {
const expArray = [];
let i = 0;
for (; i <= 10; i+=0.5) {
expArray.push(
Math.exp(i) / Math.exp(10) * 10
)
}
return expArray;
}
const generateParabolic = () => {
const paraArray = [];
let i = 0;
for (; i <= 10; i+=0.5) {
paraArray.push(
Math.pow(i - 5, 2) * 0.4
)
}
return paraArray;
}
const generateDampedOscillation = () => {
const osArray = [];
let i = 0;
for (; i <= 10; i+=0.5) {
osArray.push(
0.5 * (10 - i) * (Math.cos(Math.PI / 2.5 * i) + 1)
)
}
return osArray;
}
const generateRandom = () => {
const randomArray = [];
let i = 0;
for (; i <= 10; i+=0.5) {
randomArray.push(
Math.random() * 10
)
}
return randomArray;
}
const generateXYArray = (xArray, yArray) => {
const xyArray = []
let i = 0;
for (; i <= 20; i++) {
xyArray.push({ x: xArray[i], y: yArray[i] });
}
return xyArray;
}
const generateData = (type) => {
switch (type) {
case 1:
return generateLinear();
case 2:
return generateLogrithmic();
case 3:
return generateExponential();
case 4:
return generateParabolic();
case 5:
return generateDampedOscillation();
//generate xLinear, yLinear
case 6:
return generateXYArray(generateLinear(), generateLinear());
//generate xLinear, yLog
case 7:
return generateXYArray(generateLinear(), generateLogrithmic());
//generate xLinear, yExp
case 8:
return generateXYArray(generateLinear(), generateExponential());
default:
return generateRandom();
}
}
export default generateData;
--------------------------------------------------------
mathSelect.js
import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import { withStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import Select from '@material-ui/core/Select';
const styles = theme => ({
formControl: {
margin: theme.spacing.unit,
},
});
class SimpleSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
handleChange = event => {
this.props.callBack(event.target.value);
};
render() {
const { classes } = this.props;
return (
<FormControl className={classes.formControl}>
<InputLabel htmlFor="select-simple">{this.props.label}</InputLabel>
<Select
value={this.props.type}
onChange={this.handleChange}
inputProps={{
id: 'select-simple',
}}
>
>
<MenuItem value={1}>linear</MenuItem>
<MenuItem value={2}>logrithmic</MenuItem>
<MenuItem value={3}>exponential</MenuItem>
<MenuItem value={4}>parabolic</MenuItem>
<MenuItem value={5}>damped oscillation</MenuItem>
<MenuItem value={100}>random</MenuItem>
</Select>
</FormControl>
);
}
}
export default withStyles(styles)(SimpleSelect);
-------------------------------------------------------
colorSelect.js
import React from 'react';
import MenuItem from '@material-ui/core/MenuItem';
import FormControl from '@material-ui/core/FormControl';
import { withStyles } from '@material-ui/core/styles';
import InputLabel from '@material-ui/core/InputLabel';
import Select from '@material-ui/core/Select';
const styles = theme => ({
formControl: {
margin: theme.spacing.unit,
},
});
class SimpleSelect extends React.Component {
constructor(props) {
super(props);
this.state = {
};
}
handleChange = event => {
this.props.callBack(event.target.value);
};
render() {
const { classes } = this.props;
const menuItems = colorArray.map((item, index) =>
<MenuItem key={index} value={item}>
<div style={{ backgroundColor: item, color: item }}>..........</div>
</MenuItem>)
return (
<FormControl className={classes.formControl}>
<InputLabel htmlFor="select-simple">{this.props.label}</InputLabel>
<Select
value={this.props.colorCode}
onChange={this.handleChange}
inputProps={{
id: 'select-simple',
}}
>
{menuItems}
</Select>
</FormControl>
);
}
}
const colorArray = [
"#12939A" ,
"#ef0707" ,
"#ef2907" ,
"#ef5007" ,
"#ef6707" ,
"#ef8a07" ,
"#efd307" ,
"#dbef07" ,
"#92ef07" ,
"#35ef07" ,
"#07ef7e" ,
"#07efeb" ,
"#07c8ef" ,
"#0786ef" ,
"#072def" ,
"#6307ef" ,
"#8e07ef" ,
"#b807ef" ,
"#df07ef" ,
"#ef0799" ,
"#ef0763" ,
"#ef0707" ,
"#5b542c" ,
"#2b5b36" ,
"#2b465b" ,
"#392b5b" ,
"#5b2b52" ,
"#dee5e5" ,
"#000000" ,
];
export default withStyles(styles)(SimpleSelect);
--------------------------------------------------
reference:
https://chuanshuoge2.blogspot.com/2018/07/react-vis.html
No comments:
Post a Comment