TimeLine组件:
index.js
import React from 'react';
import {
View,
Text,
DeviceEventEmitter,
} from 'react-native';
import * as R from 'ramda';
import { PComponent } from 'rnplus';
import moment from 'moment';
import styles from './style';
import { timeLineLocation } from './func';
/**
* 时间线
*/
class TimeLine extends PComponent {
constructor (props) {
super(props);
this.state = {
time: moment().format('HH:mm'),
};
}
componentDidMount () {
this.updateLocation();
this.subscription = DeviceEventEmitter.addListener('ws_time', (time) => {
this.setState({ time });
this.updateLocation(); // 时间轴根据时间推移
});
}
shouldComponentUpdate (nextProps, nextState) {
return true;
}
componentWillReceiveProps (nextProps) {
}
componentWillUnmount () {
this.subscription.remove();
}
// 时间变化,需要移动位置
updateLocation = () => {
const {
timeLineStartTime = moment('2021-01-07 08:00'),
interval=0,
} = this.props;
const timeLine = timeLineLocation(timeLineStartTime, interval);
this.timeline.setNativeProps({
style: {
left: timeLine < 600 ? timeLine : timeLine - 225, // 提示信息在左边时减去信息长度
// left: width,
},
});
}
render () {
const { time } = this.state;
const {
unReachCountNow = false,
timeLineStartTime = moment('2021-01-07 08:00'),
timeLineContent ='请及时处理微波炉任务,超时后会自动消失',
interval=0,
} = this.props;
const timeLine = timeLineLocation(timeLineStartTime, interval);
// console.log('timeLine', timeLine);
return (
<View
style={timeLine < 600 ? styles.time : styles.timeLeft}
ref={timeline => (this.timeline = timeline)}
pointerEvents="none"
>
<View style={timeLine < 600 ? styles.timeAndunReach : styles.timeAndunReachLeft}>
<View style={styles.timeValue}>
<Text style={styles.timeDesc}>{time}</Text>
</View>
{
unReachCountNow ?
<View style={timeLine < 600 ? styles.unReachCountValue : styles.unReachCountValueLeft}>
<Text style={styles.timeDesc}>{timeLineContent}</Text>
</View>
: null
}
</View>
<View style={timeLine < 600 ? styles.timeLine : styles.timeLineLeft} pointerEvents="none">
{R.repeat('', 25).map(() => <Text style={styles.timeLineArea} />)}
</View>
</View>
);
}
}
export default TimeLine;
style.js
import { StyleSheet } from 'react-native';
import transPxToDp from 'rnx-ui/util/transPxToDp';
const pxCalculate = size => Math.round(transPxToDp(size));
export default StyleSheet.create({
time: {
width: pxCalculate(450),
position: 'absolute',
top: 0,
zIndex: 999,
flex:1,
},
timeValue: {
width: pxCalculate(55),
height: pxCalculate(25),
borderRadius: pxCalculate(4),
backgroundColor: 'rgb(55,197,56)',
alignItems: 'flex-start',
justifyContent: 'center',
},
unReachCountValue: {
width: pxCalculate(400),
backgroundColor: 'rgb(255,62,0)',
height: pxCalculate(25),
borderRadius: pxCalculate(4),
alignItems: 'flex-start',
justifyContent: 'center',
marginLeft: pxCalculate(3)
},
timeDesc: {
color: '#ffffff',
fontSize: pxCalculate(20),
},
timeLine: {
flex: 1,
justifyContent: 'space-between',
marginLeft: pxCalculate(27) // 时间轴的线定位到时间text的中间
},
timeLineArea: {
width: pxCalculate(1),
height: pxCalculate(3),
marginTop: pxCalculate(2),
// flex: 1,
marginTop: pxCalculate(2),
backgroundColor: '#FF0000',
},
timeAndunReach: {
width: pxCalculate(450),
flexDirection: 'row',
},
timeLeft: {
// width: NEW_HOME_TIME_LINE_WIDTH,
width: pxCalculate(900),
position: 'absolute',
top: 0,
zIndex: 999,
flex: 1,
backgroundColor: 'transparent',
},
timeLineLeft: {
flex: 1,
justifyContent: 'space-between',
marginLeft: pxCalculate(55), // 时间轴的线定位到时间text的中间
alignSelf: 'center',
},
timeAndunReachLeft: {
width: pxCalculate(900),
flexDirection: 'row',
marginLeft: pxCalculate(450),
},
unReachCountValueLeft: {
marginLeft: pxCalculate(-463),
width: pxCalculate(400),
backgroundColor: 'rgb(255,62,0)',
height: pxCalculate(25),
borderRadius: pxCalculate(4),
alignItems: 'flex-start',
justifyContent: 'center',
},
});
func.js
import moment from 'moment';
import {
Dimensions
} from 'react-native';
const { width } = Dimensions.get('window');
export const timeLineLocation = (timeLineStartTime, interval) => {
const hours = moment().hour();
const minutes = moment().minute();
const des = moment(timeLineStartTime).hour() * 60;
const allMinutes = hours * 60 + minutes;
const left = (width / interval) / 60 * (allMinutes - des ) - 5; // 位置 = left - 组件宽度 / 2
return left;
};
TimeLine组件应用:
index.js
this.timeLineStartTime= moment('2021-01-07 07:00'); // 时间轴开始时间
this.timeLineEndTime=moment('2021-01-07 22:58'); // 时间轴结束时间
this.timeLineContent = '提示信息';
const { width } = Dimensions.get('window');
...
// 计算开始结束时间的整点数
intervalHours = (startTime, endTime) => {
const startHour = moment(startTime).hour();
const endMinute = moment(endTime).minute();
const endHour = moment(endTime).hour() + (endMinute > 0 ? 1 : 0);
return {
startHour,
endHour
};
}
// 计算时间轴小时数
getHours = (startHour, endHour) => {
const interval = endHour - startHour;
return R.repeat('', interval).map((item, index) => `${index + startHour}:00`);
}
...
render() {
const {
timeLineStartTime,
timeLineEndTime,
timeLineContent,
} = this;
const {
startHour = 0,
endHour = 0,
} = this.intervalHours(timeLineStartTime, timeLineEndTime);
const interval = endHour - startHour; // 开始结束的时间差
return (
<View style={
{ width: width, flexDirection: 'row', justifyContent: 'space-around', backgroundColor: '#313D4F', display: 'inline' }}>
{this.getHours(startHour, endHour).map(item => <Text style={styles.hour}>{item}</Text>)}
{/* 时间段分割线 */}
{R.repeat('', interval * 2).map((line, index) => <View style={[styles.line, { left: Number(index) * (width / (interval * 2)) + 10 }]} />)}
<TimeLine
unReachCountNow={unReachCountNow}
timeLineStartTime={timeLineStartTime}
timeLineEndTime={timeLineEndTime}
timeLineContent={timeLineContent}
interval={interval}
/>
</View>
)
}
style.js
hour: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'transparent',
color: '#ffffff',
fontSize: pxCalculate(20),
textAlignVertical: 'center',
height: pxCalculate(70),
},
line: {
position: 'absolute',
bottom: 0,
width: StyleSheet.hairlineWidth,
backgroundColor: '#DDDDDD',
height: pxCalculate(15),
},