私はReact generate SVGを使って可視化アプリケーションを作成しています。私が必要とする部分の1つは、ラベル(つまり、囲み枠で囲まれたテキスト、可変テキスト付き、可能であれば回転およびスタイル付き)です。SVGバウンディングボックスのReact?
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>
}
そして、私はここで、DOMでこのことについていくつかの情報を見つけた:
は、だから私は、固定された寸法で、現在、NodeLabel
のためのコンポーネントを持ってRectangle border around SVG text
をしかし、私は「ドンこれをReactコンポーネントに変換する方法をよく見てください。render()メソッドの内部では、見るべきDOM要素はありません。代わりにdocument.createElement()
を使用して、SVG要素のディメンションが正しく動作する(そしてCSSに敬意を表する)ことを期待できますか?また、作成コードを本質的に2つコピーするのを避ける方法はありますか?JSXに1つ、直前に1つです。 (たとえば、この一時的なオフスクリーンコピーのJSXスニペットをDOM要素に評価するなど)
更新:2018年1月更新:実際のアプリケーションはオープンソースのネットワーク図です現在GDとPHPを使用していますが、JS、React、SVGに移行しています。
ここでの帯域幅ラベルは、私が再現しようとしているラベルですが、ノードラベルは現在の非SVGバージョンで同じ機能を使用しています。ここで
私の新しい最小限の例である:あなたのいずれかの事前計算/あなたの書体の形状を測定し、入力に基づいてテキストの大きさの合理的な見積りを取得
// MyLabel should be centred at x,y, rotated by angle,
// and have a bounding box around it, 2px from the text.
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>;
// label isn't a DOM element, so you can't call label.getBoundingClientRect() or getBBox()
// (Magic happens here to find bbox of label..)
// make up a static one for now
let bb = {x: this.props.x-20, y: this.props.y-6, width: 40, height: 12};
// add margin
const margin = 2;
bb.width += margin * 2;
bb.height += margin * 2;
bb.x -= margin;
bb.y -= margin;
// rect uses bbox to decide its size and position
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})`;
// build the final label (plus an x,y spot for now)
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>
それだけでなく、質問内の最小限の例を含めることが良いでしょう。 – Jeroen
本当です。私は今それを追加します。 – AnotherHowie
bboxを入手するのに反応型リファレンスを使用しないのはなぜですか? –