Skip to content

Commit

Permalink
Work out last few issues in touch
Browse files Browse the repository at this point in the history
  • Loading branch information
nickclaw committed May 15, 2017
1 parent 6c7895c commit fa7db13
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 23 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -5,6 +5,8 @@
* Adds a hard dependency on using `react-dnd` which was theoretically
optional before.
* Fix double dispatch of `onDragOver` prop
* Default strength functions always return 0 if the point is anywhere
outside the box.

### `v3.2.0`
* Use `prop-types` package instead of deprecated `React.PropTypes`
Expand Down
58 changes: 35 additions & 23 deletions src/index.js
Expand Up @@ -5,15 +5,17 @@ import throttle from 'lodash.throttle';
import raf from 'raf';
import getDisplayName from 'react-display-name';
import hoist from 'hoist-non-react-statics';
import { noop, intBetween } from './util';
import { noop, intBetween, getCoords } from './util';

const DEFAULT_BUFFER = 150;

export function createHorizontalStrength(_buffer) {
return function defaultHorizontalStrength({ x, w }, point) {
return function defaultHorizontalStrength({ x, w, y, h }, point) {
const buffer = Math.min(w / 2, _buffer);
const inRange = point.x >= x && point.x <= x + w;
const inBox = inRange && point.y >= y && point.y <= y + h;

if (point.x >= x && point.x <= x + w) {
if (inBox) {
if (point.x < x + buffer) {
return (point.x - x - buffer) / buffer;
} else if (point.x > (x + w - buffer)) {
Expand All @@ -26,10 +28,12 @@ export function createHorizontalStrength(_buffer) {
}

export function createVerticalStrength(_buffer) {
return function defaultVerticalStrength({ y, h }, point) {
return function defaultVerticalStrength({ y, h, x, w }, point) {
const buffer = Math.min(h / 2, _buffer);
const inRange = point.y >= y && point.y <= y + h;
const inBox = inRange && point.x >= x && point.x <= x + w;

if (point.y >= y && point.y <= y + h) {
if (inBox) {
if (point.y < y + buffer) {
return (point.y - y - buffer) / buffer;
} else if (point.y > (y + h - buffer)) {
Expand Down Expand Up @@ -75,11 +79,17 @@ export default function createScrollingComponent(WrappedComponent) {
this.scaleX = 0;
this.scaleY = 0;
this.frame = null;

this.attached = false;
this.dragging = false;
}

componentDidMount() {
this.container = findDOMNode(this.wrappedInstance);
this.container.addEventListener('dragover', this.handleEvent);
// touchmove events don't seem to work across siblings, so we unfortunately
// have to attach the listeners to the body
window.document.body.addEventListener('touchmove', this.handleEvent);

this.clearMonitorSubscription = this.context
.dragDropManager
Expand All @@ -88,46 +98,48 @@ export default function createScrollingComponent(WrappedComponent) {
}

componentWillUnmount() {
this.container.removeEventListener('dragover', this.handleEvent);
window.document.body.removeEventListener('touchmove', this.handleEvent);
this.clearMonitorSubscription();
this.stopScrolling();
}

getCoords(evt) {
if (evt.type === 'touchmove') {
return { x: evt.changedTouches[0].clientX, y: evt.changedTouches[0].clientY };
handleEvent = (evt) => {
if (this.dragging && !this.attached) {
this.attach();
this.updateScrolling(evt);
}
}

handleMonitorChange() {
const isDragging = this.context.dragDropManager.getMonitor().isDragging();

return { x: evt.clientX, y: evt.clientY };
if (!this.dragging && isDragging) {
this.dragging = true;
} else if (this.dragging && !isDragging) {
this.dragging = false;
this.stopScrolling();
}
}

attach() {
this.attached = true;
window.document.body.addEventListener('mousemove', this.updateScrolling);
window.document.body.addEventListener('dragover', this.updateScrolling);
window.document.body.addEventListener('touchmove', this.updateScrolling);
}

detach() {
this.attached = false;
window.document.body.removeEventListener('mousemove', this.updateScrolling);
window.document.body.removeEventListener('dragover', this.updateScrolling);
window.document.body.removeEventListener('touchmove', this.updateScrolling);
}

handleMonitorChange() {
const isDragging = this.context.dragDropManager.getMonitor().isDragging();

if (!this.attached && isDragging) {
this.attach();
} else if (this.attached && !isDragging) {
this.stopScrolling();
}
}

// Update scaleX and scaleY every 100ms or so
// and start scrolling if necessary
updateScrolling = throttle(evt => {
const { left: x, top: y, width: w, height: h } = this.container.getBoundingClientRect();
const box = { x, y, w, h };
const coords = this.getCoords(evt);
const coords = getCoords(evt);

// calculate strength
this.scaleX = this.props.horizontalStrength(box, coords);
Expand Down Expand Up @@ -189,7 +201,7 @@ export default function createScrollingComponent(WrappedComponent) {
tick();
}

stopScrolling = () => {
stopScrolling() {
this.detach();
this.scaleX = 0;
this.scaleY = 0;
Expand Down
9 changes: 9 additions & 0 deletions src/util.js
Expand Up @@ -8,3 +8,12 @@ export function intBetween(min, max, val) {
Math.min(max, Math.max(min, val))
);
}


export function getCoords(evt) {
if (evt.type === 'touchmove') {
return { x: evt.changedTouches[0].clientX, y: evt.changedTouches[0].clientY };
}

return { x: evt.clientX, y: evt.clientY };
}
Expand Up @@ -24,6 +24,11 @@ describe('strength functions', function() {
expect(hFn(box, { x: 450, y: 0 })).to.equal(0);
});

it('should return 0 when outside the box', function() {
expect(hFn(box, { x: 0, y: -100 })).to.equal(0);
expect(hFn(box, { x: 0, y: 900 })).to.equal(0);
});

it('should scale linearly from the boundary to respective buffer', function() {
expect(hFn(box, { x: 75, y: 0 })).to.equal(-.5);
expect(hFn(box, { x: 525, y: 0 })).to.equal(.5);
Expand Down Expand Up @@ -52,6 +57,11 @@ describe('strength functions', function() {
expect(vFn(box, { x: 0, y: 450 })).to.equal(0);
});

it('should return 0 when outside the box', function() {
expect(vFn(box, { x: -100, y: 0 })).to.equal(0);
expect(vFn(box, { x: 900, y: 0 })).to.equal(0);
});

it('should scale linearly from the boundary to respective buffer', function() {
expect(vFn(box, { x: 0, y: 75 })).to.equal(-.5);
expect(vFn(box, { x: 0, y: 525 })).to.equal(.5);
Expand Down

0 comments on commit fa7db13

Please sign in to comment.