terriajs
Version:
Geospatial data visualization platform.
126 lines (103 loc) • 4.59 kB
JSX
;
import createReactClass from 'create-react-class';
import dateFormat from 'dateformat';
import React from 'react';
import PropTypes from 'prop-types';
import defined from 'terriajs-cesium/Source/Core/defined';
import knockout from 'terriajs-cesium/Source/ThirdParty/knockout';
import ClockRange from 'terriajs-cesium/Source/Core/ClockRange';
import JulianDate from 'terriajs-cesium/Source/Core/JulianDate';
import ObserveModelMixin from '../../ObserveModelMixin';
import TimelineControls from './TimelineControls';
import CesiumTimeline from './CesiumTimeline';
import DateTimePicker from './DateTimePicker';
import {formatDateTime} from './DateFormats';
import Styles from './timeline.scss';
const Timeline = createReactClass({
displayName: 'Timeline',
mixins: [ObserveModelMixin],
propTypes: {
terria: PropTypes.object.isRequired,
autoPlay: PropTypes.bool,
locale: PropTypes.object
},
getDefaultProps() {
return {
autoPlay: true
};
},
getInitialState() {
return {
currentTimeString: '<>'
};
},
/* eslint-disable-next-line camelcase */
UNSAFE_componentWillMount() {
this.resizeListener = () => this.timeline && this.timeline.resize();
window.addEventListener('resize', this.resizeListener, false);
const updateCurrentTimeString = clock => {
const time = clock.currentTime;
let currentTime;
if (defined(this.props.terria.timeSeriesStack.topLayer) && defined(this.props.terria.timeSeriesStack.topLayer.dateFormat.currentTime)) {
currentTime = dateFormat(time, this.props.terria.timeSeriesStack.topLayer.dateFormat.currentTime);
} else {
currentTime = formatDateTime(JulianDate.toDate(time), this.props.locale);
}
this.setState({
currentTimeString: currentTime
});
};
this.removeTickEvent = this.props.terria.clock.onTick.addEventListener(updateCurrentTimeString);
updateCurrentTimeString(this.props.terria.clock);
this.topLayerSubscription = knockout.getObservable(this.props.terria.timeSeriesStack, 'topLayer').subscribe(() => this.updateForNewTopLayer());
this.updateForNewTopLayer();
},
componentWillUnmount() {
this.removeTickEvent();
this.topLayerSubscription.dispose();
window.removeEventListener('resize', this.resizeListener);
},
updateForNewTopLayer() {
let autoPlay = this.props.terria.autoPlay;
if(!defined(autoPlay)) {
autoPlay = this.props.autoPlay;
}
const terria = this.props.terria;
const newTopLayer = terria.timeSeriesStack.topLayer;
// default to playing and looping when shown unless told otherwise
if (newTopLayer && autoPlay) {
terria.clock.tick();
terria.clock.shouldAnimate = true;
}
terria.clock.clockRange = ClockRange.LOOP_STOP;
this.setState({
layerName: newTopLayer && newTopLayer.name
});
},
changeDateTime(time) {
this.props.terria.clock.currentTime = JulianDate.fromDate(new Date(time));
this.props.terria.currentViewer.notifyRepaintRequired();
},
render() {
const terria = this.props.terria;
const catalogItem = terria.timeSeriesStack.topLayer;
if (!defined(catalogItem)) {
return null;
}
return (
<div className={Styles.timeline}>
<div className={Styles.textRow}>
<div className={Styles.textCell} title="Name of the dataset whose time range is shown">{catalogItem.name} {this.state.currentTimeString}</div>
</div>
<div className={Styles.controlsRow}>
<TimelineControls clock={terria.clock} analytics={terria.analytics} currentViewer={terria.currentViewer} />
<If condition={defined(catalogItem.availableDates) && (catalogItem.availableDates.length !== 0)}>
<DateTimePicker currentDate={catalogItem.clampedDiscreteTime} dates={catalogItem.availableDates} onChange={this.changeDateTime} openDirection='up'/>
</If>
<CesiumTimeline terria={terria} />
</div>
</div>
);
}
});
module.exports = Timeline;