问题描述
我有一个对象数组。每个对象都有时间和状态。另外,我有一个具有特定值的时间范围,我需要在时间轴上显示它:
I want the result something like that
我想需要使用“react-native-svg”和“react-native-svg-charts”,但我不明白如何制作时间线。
如果可以,请提出解决方案。
解决方法
我已经解决了这个问题:
import React from "react";
import PropTypes from "prop-types";
import {StyleSheet,View} from "react-native";
import Icons from "react-native-vector-icons/MaterialIcons";
import {LineChart,Path} from "react-native-svg-charts";
import {ClipPath,Defs,ForeignObject,G,Rect} from "react-native-svg";
import {connect} from "react-redux";
import * as shape from "d3-shape";
import colors from "../../../styles/colors";
const TimeLine = (props) => {
// props.info.distractions - the array of red lines on the timeline (green line)
const startTime = props.info.startTs; // the start value of the timeline (GREEN line)
const endTime = props.info.endTs; // the end time value of the timeline (GREEN line)
const data = [0,0];
const line = shape.curveBasis;
// Get coefficients to scale the array of red lines into the timeline (green line)
const getCoefficients = (distraction) => {
const wholeTime = endTime - startTime;
const dZone = distraction;
const a1 = dZone.start - startTime;
const a2 = dZone.end - endTime;
const startCoefficient = a1 / wholeTime;
const endCoefficient = a2 / wholeTime;
return {startCoefficient,endCoefficient};
};
// To render a red line on the timeline (green line)
const RenderLine = ({width,distraction,index}) => {
const {startCoefficient,endCoefficient} = getCoefficients(distraction);
return (
<ClipPath id={`clip-path-${index + 1}`}>
<Rect
x={startCoefficient * width}
y={"0"}
width={endCoefficient * width}
height={"100%"}
/>
</ClipPath>
);
};
// To render a red line on the timeline (green line)
const DistractionLine = ({line,index}) => {
return (
<G key={index}>
<Path
key={`line-${index + 1}`}
d={line}
stroke={colors.red}
strokeWidth={6}
fill={"none"}
clipPath={`url(#clip-path-${index + 1})`}
/>
</G>
);
};
// To render an icon
const ChartPoint = ({width,endCoefficient} = getCoefficients(distraction);
return (
<ForeignObject
x={(startCoefficient * width + endCoefficient * width) / 2}
y={40}
width={100}
height={40}>
<Icons name={"touch-app"} color={colors.red} size={24} />
</ForeignObject>
);
};
// To render the timeline (green line)
const Clips = ({x,y,width}) => {
return (
<Defs key={"clips"}>
<ClipPath id="clip-path-0">
<Rect x={"0"} y={"0"} width={width} height={"100%"} />
</ClipPath>
{props.info.distractions.map((distraction,index) => (
<RenderLine
key={index}
index={index}
distraction={distraction}
width={width}
/>
))}
</Defs>
);
};
return (
<View style={styles.chartContainer}>
<Icons
name={"radio-button-checked"}
size={24}
color={colors.red}
style={{marginRight: -2,marginBottom: 10}}
/>
<LineChart
style={{height: 70,width: "90%"}}
data={data}
contentInset={{top: 0,bottom: 40}}
curve={line}
svg={{
stroke: colors.green,strokeWidth: 6,clipPath: "url(#clip-path-0)",}}>
<Clips />
{props.info.distractions.map((distraction,index) => (
<ChartPoint
key={index}
index={index}
distraction={distraction}
/>
))}
{props.info.distractions.map((distraction,index) => (
<DistractionLine
key={index}
index={index}
distraction={distraction}
/>
))}
</LineChart>
<Icons
name={"place"}
size={24}
color={colors.red}
style={{marginLeft: -6,marginBottom: 10}}
/>
</View>
);
};
TimeLine.defaultProps = {
info: {},};
TimeLine.propTypes = {
info: PropTypes.object,};
const styles = StyleSheet.create({
chartContainer: {
marginTop: 20,flexDirection: "row",padding: 20,paddingVertical: 20,backgroundColor: "#fff",justifyContent: "center",alignItems: "center",},});
const mapStateToProps = (state) => {
const { infoReducer } = state;
return {
info: infoReducer.info,};
};
export default connect(mapStateToProps)(TimeLine);