我正在编写一个使用React生成SVG的可视化应用程序.我需要的一个部分是标签 – 即文本,由一个封闭的盒子包围,带有可变文本,可能是旋转和样式.
所以我有一个NodeLabel的组件,目前有固定的尺寸:
render() {
return
我在DOM中找到了一些关于这样做的信息:Rectangle border around SVG text
但我不太清楚如何将其转换为React组件 – 在render()方法中,没有要查看的DOM元素.我可以只使用document.createElement()并期望SVG元素的维度正常运行(并尊重CSS)吗?另外,有没有办法避免基本上创建代码的两个副本,一个在JSX中,另一个在此之前用于计算尺寸? (比如,例如,为这个临时的屏幕外拷贝评估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 = Box()
// (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 =
body { background: gray; }
svg {background: lightgray;}
.labeloutline { fill: white; stroke: black;}
也就是说,你通过ref获取dom元素,获取mount上的框,最后通过更新状态重新渲染,例如:
class MyLabel extends React.Component {
constructor(props){
super(props);
this.state = {text_extents:null};
}
componentDidMount() {
const Box = this.text.getBBox();
this.setState({text_extents:[Box.width,Box.height]});
}
render() {
const margin = 2;
const extents = this.state.text_extents;
const label =
请注意,根据最新的反应文档,这不应该在任何用户可见的闪烁中引起:
componentDidMount(): Calling setState() in this method will trigger an extra rendering,but it will happen before the browser updates the screen. This guarantees that even though the render() will be called twice in this case,the user won’t see the intermediate state. Use this pattern with caution because it often causes performance issues. It can,however,be necessary for cases like modals and tooltips when you need to measure a DOM node before rendering something that depends on its size or position.
最后,请注意,如果标签字符串发生更改(通过道具或其他),则需要相应地更新扩展区(通过componentDidUpdate()).