UNPKG

labo-components

Version:
167 lines (147 loc) 4.44 kB
import React from 'react'; import PropTypes from 'prop-types'; import IDUtil from '../../../../util/IDUtil'; import { timeToString } from './_timeHelpers'; // Render a time axis in a canvas, by the given properties class Axis extends React.PureComponent { constructor(props) { super(props); // refs this.canvasRef = React.createRef(); } componentDidUpdate() { this.renderTime(); } // get the optimal time step for rendering, so that we have always a nice number of steps in the view getTimeStep(start, end, width) { // get time step const stepsInScreen = Math.max(1, Math.round(width / 300)); const duration = end - start; //const validSteps = [0.1, 0.5, 1, 5, 10, 60, 300, 900, 1800, 3600]; //sec const validSteps = [1, 10, 60, 600, 1800, 3600]; //sec const realStep = Math.max(0.1, Math.round(duration / stepsInScreen)); let smallStep = 0.1; let step = realStep; let diff = Infinity; validSteps.forEach((s, index) => { const d = Math.abs(s - realStep); if (d < diff) { diff = d; step = s; if (index > 0) { smallStep = validSteps[index - 1]; } } }); return { step, smallStep }; } // render the time to a canvas renderTime() { // get time step const { start, end, width, height, pixelsPerSecond } = this.props; const stepSize = this.getTimeStep(start, end, width); const canvas = this.canvasRef.current; const ctx = canvas.getContext('2d'); // clear ctx.fillStyle = 'black'; ctx.fillRect(0, 0, width, height); // set stroke style ctx.strokeStyle = 'white'; // Draw small step lines ctx.lineWidth = 1; this.drawBars( ctx, stepSize.smallStep, start, end - start, height, height / 5, pixelsPerSecond, false ); // Draw Step lines and labels ctx.fillStyle = 'white'; ctx.font = '13px sans'; ctx.lineWidth = 2; this.drawBars( ctx, stepSize.step, start, end - start, height, height / 2, pixelsPerSecond, true ); } // draw bars with given properties to the given context drawBars( ctx, stepSize, start, duration, height, size, pixelsPerSecond, drawLabels ) { const labels = []; // draw bars ctx.beginPath(); for ( let i = 0, x = 0, t = 0, steps = Math.ceil(duration / stepSize) + 1; i < steps; i++ ) { t = -(start % stepSize) + i * stepSize; x = t * pixelsPerSecond; ctx.moveTo(x, height - size); ctx.lineTo(x, height); ctx.stroke(); // store data for labels if (drawLabels) { labels.push({ x, time: Math.round((start + t) * 10) / 10 }); } } ctx.closePath(); // draw the labels if (drawLabels) { for ( let i = 0, steps = Math.ceil(duration / stepSize) + 1; i < steps; i++ ) { ctx.fillText( timeToString(labels[i].time, stepSize < 1), labels[i].x - 1, 15 ); } } } render() { const { width, height } = this.props; return ( <div className={IDUtil.cssClassName('tl-axis')} ref={this.ref} style={{ height }} > <canvas ref={this.canvasRef} width={width} height={height} style={{ width: '100%', height: '100%' }} ></canvas> </div> ); } } Axis.propTypes = { start: PropTypes.number.isRequired, end: PropTypes.number.isRequired, position: PropTypes.number.isRequired, width: PropTypes.number.isRequired, height: PropTypes.number.isRequired }; export default Axis;