Skip to content
This repository has been archived by the owner on Feb 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #496 from FormidableLabs/646-zoom-real-time
Browse files Browse the repository at this point in the history
make ZoomContainer work with real-time data
  • Loading branch information
boygirl authored Jul 17, 2017
2 parents 330fa10 + 558ba64 commit 2b5e178
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 43 deletions.
69 changes: 32 additions & 37 deletions demo/components/debug-demo.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,47 @@
/*eslint-disable no-magic-numbers */
/*global setInterval:false */

import React from "react";
import {
VictoryChart, VictoryLine, VictoryGroup, VictoryBrushContainer
VictoryChart, VictoryLine, VictoryZoomContainer
} from "../../src/index";

const data = [
{ x: 1, y: -3 },
{ x: 2, y: 5 },
{ x: 3, y: 3 },
{ x: 4, y: 0 },
{ x: 5, y: -2 },
{ x: 6, y: -2 },
{ x: 7, y: 5 }
];
import { range, last } from "lodash";

const y = (x) => Math.sin(x / 10);
const initData = () => range(70).map((x) => ({ x, y: y(x) }));

class App extends React.Component {
constructor() {
super();
this.state = {};
}
handleSelectionChange(domain) {
this.setState({
selectedDomain: domain
});
}
changeSelection(a, b) {
this.setState({
selectedDomain: { x: [a, b] }
});
this.state = {
data: initData(),
zoomDomain: null
};

setInterval(() => {
const { data } = this.state;
const x = last(data).x + 1;

if (x > 1000) {
this.setState({ data: initData() });
} else {
data.push({ x, y: y(x) });
this.setState({ data });
}
}, 20);
}
render() {
return (
<div style={{ width: 300 }}>
<button onClick={() => this.changeSelection(1, 3)}>1-3</button>
<button onClick={() => this.changeSelection(3, 6)}>3-6</button>
<VictoryChart
containerComponent={
<VictoryBrushContainer
dimension="x"
onDomainChange={this.handleSelectionChange.bind(this)}
selectedDomain={this.state.selectedDomain}
/>
}
>
<VictoryGroup data={data}>
<VictoryLine/>
</VictoryGroup>
</VictoryChart>
<div style={{ maxWidth: 500 }}>
<VictoryChart containerComponent={<VictoryZoomContainer dimension="x" />}>
<VictoryLine
data={this.state.data}
/>
<VictoryLine
data={this.state.data}
/>
</VictoryChart>
</div>
);
}
Expand Down
20 changes: 16 additions & 4 deletions src/components/containers/victory-zoom-container.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ export const zoomContainerMixin = (base) => class VictoryZoomContainer extends b
static defaultProps = {
...VictoryContainer.defaultProps,
clipContainerComponent: <VictoryClipContainer/>,
allowZoom: true
allowZoom: true,
zoomActive: false
};

static defaultEvents = [{
Expand Down Expand Up @@ -131,12 +132,23 @@ export const zoomContainerMixin = (base) => class VictoryZoomContainer extends b
const childComponents = React.Children.toArray(props.children);

return childComponents.map((child) => {
const { currentDomain } = props;
const { currentDomain, zoomActive } = props;
const originalDomain = defaults({}, props.originalDomain, props.domain);
const zoomDomain = defaults({}, props.zoomDomain, props.domain);
const cachedZoomDomain = defaults({}, props.cachedZoomDomain, props.domain);
const domain = isEqual(zoomDomain, cachedZoomDomain) ?
defaults({}, currentDomain, originalDomain) : zoomDomain;

let domain;
if (!isEqual(zoomDomain, cachedZoomDomain)) {
// if zoomDomain has been changed, use it
domain = zoomDomain;
} else if (!zoomActive) {
// if user has zoomed all the way out, use the child domain
domain = child.props.domain;
} else {
// default: use currentDomain, set by the event handlers
domain = defaults({}, currentDomain, originalDomain);
}

let newDomain = props.polar ? this.modifyPolarDomain(domain, originalDomain) : domain;
if (props.dimension) {
// if zooming is restricted to a dimension, don't squash changes to zoomDomain in other dim
Expand Down
14 changes: 12 additions & 2 deletions src/components/containers/zoom-helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@ const Helpers = {
];
},

zoommingOut(evt) {
return evt.deltaY > 0;
},

getScaleFactor(evt) {
const sign = evt.deltaY > 0 ? 1 : -1;
const sign = this.zoommingOut(evt) ? 1 : -1;
// eslint-disable-next-line no-magic-numbers
const delta = Math.min(Math.abs(evt.deltaY / 300), 0.5); // TODO: Check scale factor
return Math.abs(1 + sign * delta);
Expand Down Expand Up @@ -232,16 +236,22 @@ const Helpers = {
y: dimension === "x" ? lastDomain.y : this.scale(y, evt, targetProps, "y")
};
const resumeAnimation = this.handleAnimation(ctx);

const zoomActive = !this.zoommingOut(evt) // if zoomming in or
// if zoomActive is already set AND user hasn't zoommed out all the way
|| (targetProps.zoomActive && !isEqual(originalDomain, lastDomain));

if (isFunction(onDomainChange)) {
onDomainChange(currentDomain);
}

return [{
target: "parent",
callback: resumeAnimation,
mutation: () => {
return {
domain: currentDomain, currentDomain, originalDomain, cachedZoomDomain: zoomDomain,
parentControlledProps: ["domain"], panning: false
parentControlledProps: ["domain"], panning: false, zoomActive
};
}
}];
Expand Down

0 comments on commit 2b5e178

Please sign in to comment.