gpt4 book ai didi

javascript - 使用 React.JS 检索和缓存 SVG 节点边界框​​的最佳方法

转载 作者:数据小太阳 更新时间:2023-10-29 06:06:28 26 4
gpt4 key购买 nike

我正在渲染带有标签的 SVG 组件。这些标签组件需要根据它们的文本内容(以及它们的大小)正确布局,以避免相互重叠。

要获得每个标签的真实大小,似乎每次更新标签内容时都需要双重渲染

在标签组件级别,我需要

  • 第一次渲染
  • 检索真实 SVG DOM 节点的边界框
  • 出于性能原因缓存边界框
  • 重新渲染组件以根据其缓存的边界框调整标签位置

然后,在每次重绘时:

  • 根据缓存的边界框渲染
  • 比较之前和更新的 props 之间的标签内容,如果有变化:
  • 更新并缓存标签边界框
  • 根据更新和缓存的边界框重新渲染

到目前为止,这是我实现标签组件的方式:

var Label = React.createClass({

updateBBox: function() {
// Trigger re-rendering
this.setState({
bbox: this.getDOMNode().getBBox()
});
},

componentDidMount: function() {
// Will trigger a re-rendering at mount
this.updateBBox();
},

componentDidUpdate: function(prevProps, prevState) {
// If content has changed, re-render
if (this.props.content !== prevProps.content) {
this.updateBBox();
}
},

render: function() {
// Render according to size from current bounding box if any cached
// ...
}

});

所以,我的问题不是算法,而是是否有更好的 React 兼容方法来实现它。 React 方式是否允许使用状态来缓存这种缓慢的“计算”或 DOM 访问?双重渲染对于 React 来说是一种不寻常的情况吗?

最佳答案

我个人的意见是,你应该把所有对你重要的状态都放到一个组件的状态中。所以是的,您建议的方式是正确的方式。

据我所知,双重渲染是获取 block 大小作为状态的唯一方法,因为需要先绘制 block 。由于 React 的性能如此之高,这通常不是问题。如果是,则使用 PureRenderMixin 或对子项中的 shouldComponentUpdate 进行其他检查以确保性能。

但是请注意,由于“不要重复自己”,将其编写为混入可能是明智的。

我经常做响应式 SVG 的东西,所以我经常需要 block 元素(svg 或 html)的 x、y 宽度和高度。

我写了这个叫做 BoundingRectAware 的小混音:

var shallowEqual = require('react/lib/shallowEqual');

// keep width and height of an element. You must make a "boundingRectTarget" ref
// to the element you would like to track
module.exports = {
getInitialState: function() {
return {rect: {
left: null, top: null, right: null, bottom: null, width: null, height: null
}};
},
componentDidMount: function() {
window.addEventListener("resize", this.updateDimensions);
this.updateDimensions();
},
componentWillUnmount: function() {
window.removeEventListener("resize", this.updateDimensions);
},
componentWillReceiveProps: function() {
this.updateDimensions();
},
updateDimensions: function() {
if (this.refs.boundingRectTarget) {
var rect = this.refs.boundingRectTarget.getDOMNode().getBoundingClientRect();
if (!shallowEqual(this.state.rect, rect)) {
this.setState({rect: rect});
}
}
}
};

可以这样使用:

var FooComponent = React.createClass({
mixins: [BoundingRectAware],
render: function() {
return <div className="foo-class" ref="boundingRectTarget"/>;
}
});

在 FooComponent 中,您将自动获取 boundingClientRect 作为状态。如果您在不止一个地方使用 getBBox(),我会实现类似的东西。

关于javascript - 使用 React.JS 检索和缓存 SVG 节点边界框​​的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26234252/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com