Skip to content

Instantly share code, notes, and snippets.

@olarclara
Created September 4, 2018 03:26
Show Gist options
  • Save olarclara/7c0f03f439dabaa49c4c372c9d9b58df to your computer and use it in GitHub Desktop.
Save olarclara/7c0f03f439dabaa49c4c372c9d9b58df to your computer and use it in GitHub Desktop.
import { cloneElement, Component } from 'react';
import PropTypes from 'prop-types';
class Draggable extends Component {
state = {
dragging: false,
pos: this.props.pos,
rel: null,
}
componentDidUpdate(props, state) {
if (this.state.dragging && !state.dragging) {
document.addEventListener('mousemove', this.onMouseMove);
document.addEventListener('mouseup', this.onMouseUp);
} else if (!this.state.dragging && state.dragging) {
document.removeEventListener('mousemove', this.onMouseMove);
document.removeEventListener('mouseup', this.onMouseUp);
}
}
onMouseDown = e => {
if (e.button !== 0) return;
const pos = this.element.getBoundingClientRect();
this.setState({
dragging: true,
rel: {
x: e.pageX - pos.left,
y: e.pageY - pos.top,
},
});
e.stopPropagation();
e.preventDefault();
}
onMouseMove = e => {
console.log(e);
if (!this.state.dragging) return;
this.setState({
pos: {
x: e.pageX - this.state.rel.x,
y: e.pageY - this.state.rel.y,
},
});
e.stopPropagation();
e.preventDefault();
}
onMouseUp = e => {
this.setState({ dragging: false });
e.stopPropagation();
e.preventDefault();
}
render() {
this.children = cloneElement(this.props.children, {
onMouseDown: this.onMouseDown,
ref: ref => { this.element = ref; },
style: {
background: 'black',
color: 'white',
cursor: 'pointer',
position: 'absolute',
left: `${this.state.pos.x}px`,
top: `${this.state.pos.y}px`,
},
});
return this.children;
}
}
Draggable.propTypes = {
pos: PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number,
}),
};
Draggable.defaultProps = {
pos: {
x: 0,
y: 0,
},
};
export default Draggable;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment