Skip to content

Commit 8e56d05

Browse files
author
Chris Thomas
committed
first attempt to fix highlighting
1 parent e47597a commit 8e56d05

File tree

2 files changed

+132
-26
lines changed

2 files changed

+132
-26
lines changed

packages/react-vis/src/plot/highlight.js

Lines changed: 112 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ import {getAttributeScale} from 'utils/scales-utils';
66
import {getCombinedClassName} from 'utils/styling-utils';
77

88
function getLocs(evt) {
9-
const xLoc = evt.type === 'touchstart' ? evt.pageX : evt.offsetX;
10-
const yLoc = evt.type === 'touchstart' ? evt.pageY : evt.offsetY;
9+
// const xLoc = evt.type === 'touchstart' ? evt.pageX : evt.offsetX;
10+
// const yLoc = evt.type === 'touchstart' ? evt.pageY : evt.offsetY;
11+
const xLoc = evt.offsetX ?? evt.pageX;
12+
const yLoc = evt.offsetY ?? evt.pageY;
1113
return {xLoc, yLoc};
1214
}
1315

@@ -20,7 +22,7 @@ class Highlight extends AbstractSeries {
2022
startLocY: 0,
2123
dragArea: null
2224
};
23-
25+
ref = React.createRef();
2426
_getDrawArea(xLoc, yLoc) {
2527
const {startLocX, startLocY} = this.state;
2628
const {
@@ -116,10 +118,69 @@ class Highlight extends AbstractSeries {
116118
return {};
117119
}
118120

119-
startBrushing(e) {
121+
_captureMouse = e => {
122+
console.log('capture', e.type, e.target, e);
123+
124+
document.addEventListener('mouseup', this.stopBrushing, {capture: true});
125+
document.addEventListener('mousemove', this.onBrush, {capture: true});
126+
// document.body.style['pointer-events'] = 'none';
127+
128+
if (this.ref.current) {
129+
this.ref.current.addEventListener('mouseleave', this._mouseLeave, {
130+
capture: true
131+
});
132+
}
133+
134+
e.preventDefault();
135+
e.stopPropagation();
136+
// this.startBrushing(e);
137+
};
138+
139+
_releaseMouse = e => {
140+
console.log('release', e.type, e.target, e);
141+
142+
document.removeEventListener('mouseup', this.stopBrushing, {capture: true});
143+
document.removeEventListener('mousemove', this.onBrush, {capture: true});
144+
145+
if (this.ref.current) {
146+
this.ref.current.removeEventListener('mouseleave', this._mouseLeave, {
147+
capture: true
148+
});
149+
}
150+
// document.body.style['pointer-events'] = 'auto';
151+
e.stopPropagation();
152+
};
153+
154+
_mouseLeave = e => {
155+
const {toElement} = e;
156+
if (toElement === document.documentElement) {
157+
this.stopBrushing(e);
158+
return;
159+
}
160+
if (toElement === this.ref.current.parentNode.parentNode) {
161+
this.stopBrushing(e);
162+
return;
163+
}
164+
console.log('didnt really leave', toElement, this.ref.current.parentNode);
165+
// this.ref.current.
166+
};
167+
168+
startBrushing = e => {
169+
// e.preventDefault();
170+
this._captureMouse(e);
120171
const {onBrushStart, onDragStart, drag} = this.props;
121172
const {dragArea} = this.state;
122-
const {xLoc, yLoc} = getLocs(e.nativeEvent);
173+
const {xLoc, yLoc} = getLocs(e);
174+
console.log(
175+
'start',
176+
xLoc,
177+
yLoc,
178+
e.type,
179+
e.offsetX,
180+
e.offsetY,
181+
e.pageX,
182+
e.pageY
183+
);
123184

124185
const startArea = (dragging, resetDrag) => {
125186
const emptyBrush = {
@@ -153,9 +214,23 @@ class Highlight extends AbstractSeries {
153214
onDragStart(e);
154215
}
155216
}
156-
}
217+
};
157218

158-
stopBrushing() {
219+
stopBrushing = e => {
220+
if (e.toElement === document.documentElement) {
221+
console.log('is document');
222+
// return;
223+
}
224+
console.log(
225+
'stop',
226+
e.type,
227+
e.target,
228+
e.currentTarget,
229+
e.toElement,
230+
document,
231+
e
232+
);
233+
this._releaseMouse(e);
159234
const {brushing, dragging, brushArea} = this.state;
160235
// Quickly short-circuit if the user isn't brushing in our component
161236
if (!brushing && !dragging) {
@@ -183,14 +258,18 @@ class Highlight extends AbstractSeries {
183258
if (drag && onDragEnd) {
184259
onDragEnd(!isNulled ? this._convertAreaToCoordinates(brushArea) : null);
185260
}
186-
}
261+
};
187262

188-
onBrush(e) {
263+
onBrush = e => {
264+
e.preventDefault();
265+
e.stopPropagation();
189266
const {onBrush, onDrag, drag} = this.props;
190267
const {brushing, dragging} = this.state;
191-
const {xLoc, yLoc} = getLocs(e.nativeEvent);
268+
const {xLoc, yLoc} = getLocs(e);
269+
// console.log('brush', xLoc, yLoc);
192270
if (brushing) {
193271
const brushArea = this._getDrawArea(xLoc, yLoc);
272+
// console.log('brush area', brushArea);
194273
this.setState({brushArea});
195274

196275
if (onBrush) {
@@ -205,7 +284,7 @@ class Highlight extends AbstractSeries {
205284
onDrag(this._convertAreaToCoordinates(brushArea));
206285
}
207286
}
208-
}
287+
};
209288

210289
render() {
211290
const {
@@ -250,26 +329,36 @@ class Highlight extends AbstractSeries {
250329
className={getCombinedClassName(className, 'rv-highlight-container')}
251330
>
252331
<rect
332+
ref={this.ref}
253333
className="rv-mouse-target"
254334
fill="black"
255335
opacity="0"
256336
x="0"
257337
y="0"
258338
width={Math.max(touchWidth, 0)}
259339
height={Math.max(touchHeight, 0)}
260-
onMouseDown={e => this.startBrushing(e)}
261-
onMouseMove={e => this.onBrush(e)}
262-
onMouseUp={e => this.stopBrushing(e)}
263-
onMouseLeave={e => this.stopBrushing(e)}
340+
onMouseDownCapture={e => this.startBrushing(e.nativeEvent)}
341+
// onMouseMoveCapture={e => this.onBrush(e)}
342+
// onMouseUpCapture={e => this.stopBrushing(e)}
343+
// onMouseLeave={e => {
344+
// console.log(
345+
// 'mouse leave',
346+
// e.target,
347+
// e.currentTarget,
348+
// getLocs(e.nativeEvent)
349+
// );
350+
// // this._releaseMouse(e);
351+
// // this.stopBrushing(e);
352+
// }}
264353
// preventDefault() so that mouse event emulation does not happen
265-
onTouchEnd={e => {
266-
e.preventDefault();
267-
this.stopBrushing(e);
268-
}}
269-
onTouchCancel={e => {
270-
e.preventDefault();
271-
this.stopBrushing(e);
272-
}}
354+
// onTouchEnd={e => {
355+
// e.preventDefault();
356+
// this.stopBrushing(e);
357+
// }}
358+
// onTouchCancel={e => {
359+
// e.preventDefault();
360+
// this.stopBrushing(e);
361+
// }}
273362
onContextMenu={e => e.preventDefault()}
274363
onContextMenuCapture={e => e.preventDefault()}
275364
/>

packages/website/storybook/misc-story.js

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
/* eslint-env node */
22

3-
import React from 'react';
3+
import React, {useState, useCallback} from 'react';
44

55
import {storiesOf} from '@storybook/react';
66

7-
import {withKnobs, boolean} from '@storybook/addon-knobs/react';
7+
import {withKnobs, boolean, button} from '@storybook/addon-knobs/react';
88
import {SimpleChartWrapper} from './storybook-utils';
99
import {generateLinearData} from './storybook-data';
1010

11-
import {LineSeries, ContentClipPath} from 'react-vis';
11+
import {LineSeries, ContentClipPath, Highlight} from 'react-vis';
1212

1313
const data = generateLinearData({randomFactor: 10});
1414

@@ -28,4 +28,21 @@ storiesOf('Misc', module)
2828
<LineSeries data={data} style={{clipPath: 'url(#clip)'}} />
2929
</SimpleChartWrapper>
3030
);
31+
})
32+
.addWithJSX('Highlight', () => {
33+
const [zoom, setZoom] = useState();
34+
const onZoom = useCallback(area => {
35+
console.log('zoom', area);
36+
}, []);
37+
38+
button('Reset Zoom', () => setZoom(null), 'Zoom');
39+
40+
const xDomain = zoom ? [zoom.left, zoom.right] : undefined;
41+
42+
return (
43+
<SimpleChartWrapper xDomain={xDomain}>
44+
<Highlight onBrushEnd={onZoom} />
45+
<LineSeries data={data} />
46+
</SimpleChartWrapper>
47+
);
3148
});

0 commit comments

Comments
 (0)