labo-components
Version:
167 lines (147 loc) • 4.44 kB
JSX
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;