React
by XeniaSiskaki
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>
<div id="app"></div>
CSS
svg {
font: 10px sans-serif;
}
button {
width: 120px;
margin: 0 15px;
}
.axis path,
.axis line {
fill: none;
stroke: #000000;
shape-rendering: crispEdges;
}
.axis path {
display: none;
}
.tick line {
stroke: rgba(220, 220, 220, 0.6);
}
React
const zoom = ['x', 'y'];
const range = [-10, 10];
const sampleDate = new Date("2020-01-01T09:00:00.000Z").getTime();
const innerWidth = 390;
const innerHeight = 278;
const chartData = {
a: [{v:0, t:sampleDate-10000},{v:-1, t: sampleDate-9000},{v:0.6, t: sampleDate-8000},{v:1, t: sampleDate-7000},{v:-2, t: sampleDate-6000},{v:10, t: sampleDate-5000},{v:0.8, t: sampleDate-4000},{v:5.3, t: sampleDate-3000},{v:0, t: sampleDate-2000},{v:1.2, t: sampleDate-1000},{v:3, t: sampleDate},{v:4.5, t: sampleDate+1000},{v:10, t: sampleDate+2000}],
b: [{v:0.8, t:sampleDate-10000},{v:11, t: sampleDate-9000},{v:-7.9, t: sampleDate-8000},{v:22.1, t: sampleDate-7000},{v:-0.3, t: sampleDate-6000},{v:10, t: sampleDate-5000},{v:1.3, t: sampleDate-4000},{v:4.3, t: sampleDate-3000},{v:0, t: sampleDate-2000},{v:-14.4, t: sampleDate-1000},{v:3, t: sampleDate},{v:-0.1, t: sampleDate+1000},{v:10, t: sampleDate+2000}]
};
const allPoints = chartData.a.concat(chartData.b);
class Chart extends React.Component {
constructor(props) {
super(props);
const [x0, x1] = d3.extent(allPoints.map(({t}) => t));
this.state = {
zoom: 1,
viewport: { x0, x1 }
};
this.zoomPane = React.createRef();
this.svg = React.createRef();
this. line = d3.svg
.line()
.interpolate('linear')
.x(({t}) => this.xScale(t))
.y(({v}) => this.configScale(this.yScale(v)));
}
render() {
return (
<div>
<div>
<button onClick={this.handleZoomChange.bind(this)}>Set zoom to {zoom[this.getNextZoomIndex()]}</button>
<button onClick={this.resetViewport.bind(this)}>Reset viewport</button>
</div>
<div style={{ height: 300 }}>
<svg width={450} height={300} ref={this.svg}>
<rect ref={this.zoomPane} style={{cursor: 'move'}} width={innerWidth} height={innerHeight} fill='transparent' transform='translate(55,0)'></rect>
<defs>
<clipPath id={'clipId'}>
...