<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="author" content="https://github.com/josdejong/">
<title>Render dynamic SVG's with React</title>
<style>
body {
font-family: verdana, sans-serif;
}
#container {
width: 100%;
text-align: center;
}
#smiley {
display: inline-block;
background: #fffdae;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.6.15/browser-polyfill.min.js"></script>
<script type="text/babel">
"use strict";
class Smiley extends React.Component {
constructor(props) {
super(props);
this.state = {
x: 0,
y: 0
}
}
render() {
let radius = Math.min(this.props.width, this.props.height) / 2;
let strokeWidth = radius / 20;
let cx = this.props.width / 2;
let cy = this.props.height / 2;
return <svg ref="svg" {...this.props} onMouseMove={this.handleMouseMove.bind(this)}>
{this.renderHead(cx, cy, radius, strokeWidth)}
{this.renderEye(cx - radius/3, cy - radius/5, radius/4, strokeWidth)}
{this.renderEye(cx + radius/3, cy - radius/5, radius/4, strokeWidth)}
{this.renderMouth(cx - 0.6 * radius, 1.3 * radius, 1.2 * radius, strokeWidth)}
</svg>;
}
renderHead (cx, cy, radius, strokeWidth) {
return <circle cx={cx} cy={cy} r={radius - 10} fill="gold" stroke="black" strokeWidth={strokeWidth} />;
}
renderEye (cx, cy, radius, strokeWidth) {
let angle = Math.atan2(this.state.y - cy, this.state.x - cx); // angle
let bcx = cx + radius / 2 * Math.cos(angle);
let bcy = cy + radius / 2 * Math.sin(angle);
return [
<circle key="eye" cx={cx} cy={cy} r={radius} fill="white" stroke="black" strokeWidth={strokeWidth} />,
<circle key="eyeball" cx={bcx} cy={bcy} r={radius/2} fill="black"/>
];
}
renderMouth (left, top, width, strokeWidth) {
let bottom = top + width * 2/5;
let path = `M${left} ${top} C ${left + 0.25*width} ${bottom}, ${left + 0.75*width} ${bottom}, ${left+width} ${top}`;
return <path d={path} stroke="black" strokeWidth={strokeWidth} fill="transparent"/>;
}
handleMouseMove (event) {
let svg = React.findDOMNode(this.refs.svg);
let rect = svg.getBoundingClientRect();
this.setState({
x: event.clientX - rect.left,
y: event.clientY - rect.top
});
}
}
React.render( <Smiley width="600" height="400" />, document.getElementById('smiley'));
</script>
</head>
<body>
<div id="container">
<h1>Render dynamic SVG's with React</h1>
<p>move your mouse over the smiley below...</p>
<div id="smiley"></div>
<p>Have fun!</p>
</div>
</body>
</html>
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |