Created
January 29, 2015 13:38
-
-
Save cirocosta/6c247b263fa2a2c61d7d to your computer and use it in GitHub Desktop.
Draggable React SVG Element
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'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