Skip to content

Instantly share code, notes, and snippets.

@cirocosta
Created January 29, 2015 13:38
Show Gist options
  • Save cirocosta/6c247b263fa2a2c61d7d to your computer and use it in GitHub Desktop.
Save cirocosta/6c247b263fa2a2c61d7d to your computer and use it in GitHub Desktop.
Draggable React SVG Element
'use strict';
/**
* DraggableSvgComp ...
*/
const findSvgRoot = (DOMNode) =>
DOMNode.parentElement.localName === 'svg' ?
DOMNode.parentElement :
findSvgRoot(DOMNode.parentElement);
const clone = (obj) => JSON.parse(JSON.stringify(obj));
const React = require('react');
const DraggableSvgComp = React.createClass({
propTypes: {
offsetX: React.PropTypes.number.isRequired,
offsetY: React.PropTypes.number.isRequired,
kind: React.PropTypes.string.isRequired,
id: React.PropTypes.string.isRequired,
},
getInitialState () {
return {
moving: false,
transX: 0,
transY: 0
}
},
_TrueCoords: null,
_GrabPoint: null,
_SVGRoot: null,
componentDidMount () {
this._SVGRoot = findSvgRoot(this.getDOMNode());
this._TrueCoords = this._SVGRoot.createSVGPoint();
this._GrabPoint = this._SVGRoot.createSVGPoint();
},
handleMouseDown (evt) {
let {e, f} = evt.target.getCTM();
this._GrabPoint.x = this._TrueCoords.x - Number(e);
this._GrabPoint.y = this._TrueCoords.y - Number(f);
this.setState({
moving: true,
transX: this.state.transX,
transY: this.state.transY
});
},
handleMouseMove (e) {
let {x, y} = this._SVGRoot.currentTranslate;
this._TrueCoords.x = (e.clientX - x)/this._SVGRoot.currentScale;
this._TrueCoords.y = (e.clientY - y)/this._SVGRoot.currentScale;
if (!this.state.moving)
return;
this.setState({
moving: true,
transX: this._TrueCoords.x - this._GrabPoint.x,
transY: this._TrueCoords.y - this._GrabPoint.y
});
},
handleMouseUp () {
this.setState({
moving: false,
transX: this.state.transX,
transY: this.state.transY
});
},
render () {
return (
<circle className="DraggableSvgComp draggable"
onMouseDown={this.handleMouseDown}
onMouseUp={this.handleMouseUp}
onMouseMove={this.handleMouseMove}
cx={this.props.offsetX} cy={this.props.offsetY}
r="40"
transform={`translate(${this.state.transX},${this.state.transY})`}
fill="orange"
stroke="navy" strokeWidth="10" />
);
}
});
module.exports = DraggableSvgComp;
'use strict';
/**
* Svg ...
*/
require('./Svg.sass');
const React = require('react');
const clone = (obj) => JSON.parse(JSON.stringify(obj));
const AudioSVGComponent = require('./AudioSVGComponent.jsx');
const Svg = React.createClass({
getInitialState () {
return {
elems: []
}
},
handleDrop (e) {
let {offsetX, offsetY} = e.nativeEvent;
let {kind, id} = JSON.parse(e.dataTransfer.getData('text/plain'));
let state = clone(this.state);
state.elems.push({kind, id, offsetX, offsetY});
this.setState(state);
},
render () {
let elems = this.state.elems.map((elem) =>
<AudioSVGComponent offsetX={elem.offsetX}
offsetY={elem.offsetY}
kind={elem.kind}
id={elem.id}/>
);
return (
<svg className="Svg" style={{background: '#e2e2e2'}}
onDrop={this.handleDrop} >
{elems}
</svg>
);
}
});
module.exports = Svg;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment