Skip to content

Instantly share code, notes, and snippets.

@kjperkin
Created June 2, 2019 00:12
Show Gist options
  • Save kjperkin/dee8c05c89fc682ad56d77e770e8c5a4 to your computer and use it in GitHub Desktop.
Save kjperkin/dee8c05c89fc682ad56d77e770e8c5a4 to your computer and use it in GitHub Desktop.
SVG Editor
<div id="app"></div>
const examples = [
{
name: 'Target',
content: `
<svg width="256px" height="256px">
<g>
<circle cx="50%" cy="50%" r="75%" fill="white"/>
<circle cx="50%" cy="50%" r="70%" fill="red"/>
<circle cx="50%" cy="50%" r="65%" fill="white"/>
<circle cx="50%" cy="50%" r="60%" fill="red"/>
<circle cx="50%" cy="50%" r="55%" fill="white"/>
<circle cx="50%" cy="50%" r="50%" fill="red"/>
<circle cx="50%" cy="50%" r="45%" fill="white"/>
<circle cx="50%" cy="50%" r="40%" fill="red"/>
<circle cx="50%" cy="50%" r="35%" fill="white"/>
<circle cx="50%" cy="50%" r="30%" fill="red"/>
<circle cx="50%" cy="50%" r="25%" fill="white" />
<circle cx="50%" cy="50%" r="20%" fill="red" />
<circle cx="50%" cy="50%" r="15%" fill="white" />
<circle cx="50%" cy="50%" r="10%" fill="red" />
<circle cx="50%" cy="50%" r="5%" fill="white" />
</g>
</svg>
`
},
{
name: 'Rainbow Circle',
content: `
<svg width="256px" height="256px">
<g>
<circle cx="50%" cy="50%" r="70%" fill="red"/>
<circle cx="50%" cy="50%" r="65%" fill="orange"/>
<circle cx="50%" cy="50%" r="60%" fill="yellow"/>
<circle cx="50%" cy="50%" r="55%" fill="green"/>
<circle cx="50%" cy="50%" r="50%" fill="blue"/>
<circle cx="50%" cy="50%" r="45%" fill="indigo"/>
<circle cx="50%" cy="50%" r="40%" fill="violet"/>
<circle cx="50%" cy="50%" r="35%" fill="red"/>
<circle cx="50%" cy="50%" r="30%" fill="orange"/>
<circle cx="50%" cy="50%" r="25%" fill="yellow"/>
<circle cx="50%" cy="50%" r="20%" fill="green" />
<circle cx="50%" cy="50%" r="15%" fill="blue" />
<circle cx="50%" cy="50%" r="10%" fill="indigo" />
<circle cx="50%" cy="50%" r="5%" fill="violet" />
<circle cx="50%" cy="50%" r="1%" fill="red" />
</g>
</svg>
`
}
];
function debounce(func, ms) {
let timeout;
return function _debounced(...args) {
clearTimeout(timeout);
timeout = setTimeout(func, ms, ...args);
};
}
class SVGEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
pendingXML: "",
xml: ""
};
this._ref = React.createRef();
this.handleInput = this.handleInput.bind(this);
this.applyPendingXML = debounce(this.applyPendingXML.bind(this), 400);
}
componentDidUpdate(prevProps, prevState) {
if (prevState.xml !== this.state.xml) {
try {
this._ref.current.innerHTML = this.state.xml;
} catch (err) {
switch (true) {
case err instanceof SyntaxError:
case err instanceof NoModificationAllowedError:
break;
default:
throw err;
}
}
}
}
render() {
return (
<div>
<h1>SVG Editor</h1>
<div>
<ul className="examples">
{examples.map((example, idx) => {
const showExample = () => {
this.setState({
pendingXML: example.content.trim(),
xml: example.content.trim()
});
}
return (
<li key="example{idx}"><a className="link" onClick={showExample}>Example {idx+1}: {example.name}</a></li>
);
})}
</ul>
</div>
<div>
<h2>Input</h2>
<textarea id="inputArea" onChange={this.handleInput} value={this.state.pendingXML}/>
</div>
<div>
<h2>Output</h2>
<div id="outputArea" className="output" ref={this._ref} />
</div>
</div>
);
}
handleInput(e) {
this.setState({ pendingXML: e.target.value }, () => this.applyPendingXML());
}
applyPendingXML() {
this.setState((state, props) => {
return { xml: state.pendingXML };
});
}
}
ReactDOM.render(<SVGEditor />, document.getElementById("app"));
<script src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
<script src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
#inputArea {
min-width: 60vw;
min-height: 30vh;
}
#outputArea {
min-width: 60vw;
min-height: 30vh;
}
a.link {
color: blue;
}
a.link:hover {
text-decoration: underline;
cursor: pointer;
}
a.link:active {
text-decoration: underline;
}
ol.examples, ul.examples {
list-style-type: none;
padding: 0px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment