I am writing a visualization application using React generating SVG. One of the parts I need is a label, that is, text surrounded by a closing box, with variable text, possibly rotated and styled.
So, I have a component for NodeLabel, currently with fixed sizes:
render() {
return <g>
<rect className="label" x={this.props.x} y={this.props.y-10} width={20} height={40}></rect>
<text className="labelText" x={this.props.x} y={this.props.y}>{this.props.children}</text>
</g>
}
And I found some information about this in the DOM, here: The rectangular border around the SVG text
But I don’t quite understand how to translate this into a React component - there are no DOM elements to view inside the render () method. Can I just use it document.createElement()instead and expect the dimensions of the SVG elements to correctly lead (and respect CSS)? Also, is there a way to avoid essentially two copies of the creation code: one in JSX and one immediately before that for sizing? (for example, to evaluate the JSX fragment for DOM elements for this temporary copy off-screen)
Update: January 2018, and I will come back to this again :-) The actual application is an open source charting tool currently using GD and PHP, but hopefully move on to JS, React and SVG.
- , , node , SVG.

:
class MyLabel extends React.Component {
render() {
const label = <text x={this.props.x} y={this.props.y} textAnchor="middle" alignmentBaseline="central">{this.props.children}</text>;
let bb = {x: this.props.x-20, y: this.props.y-6, width: 40, height: 12};
const margin = 2;
bb.width += margin * 2;
bb.height += margin * 2;
bb.x -= margin;
bb.y -= margin;
const outline = <rect x={bb.x} y={bb.y} width={bb.width} height={bb.height} className="labeloutline"></rect>;
const rot = `rotate(${this.props.angle} ${this.props.x} ${this.props.y})`;
return <g transform={rot}>{outline}{label}<circle cx={this.props.x} cy={this.props.y} r="2" fill="red" /></g>;
}
}
class Application extends React.Component {
render() {
return <svg width={300} height={300}>
<MyLabel x={100} y={100} angle={0}>Dalmation</MyLabel>
<MyLabel x={200} y={100} angle={45}>Cocker Spaniel</MyLabel>
<MyLabel x={100} y={200} angle={145}>Pug</MyLabel>
<MyLabel x={200} y={200} angle={315}>Pomeranian</MyLabel>
</svg>;
}
}
/*
* Render the above component into the div#app
*/
ReactDOM.render(<Application />, document.getElementById('app'));
body { background: gray; }
svg {background: lightgray;}
.labeloutline { fill: white; stroke: black;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>