使用React.JS检索和缓存SVG节点的边界框的最佳方法 [英] Best way to retrieve and cache bounding boxes of SVG nodes with React.JS

查看:98
本文介绍了使用React.JS检索和缓存SVG节点的边界框的最佳方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am rendering a SVG component with labels. Those label components need to be correctly laid out depending on their text content (and so their size) in order to avoid overlapping themselves.

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

To get the real size of each labels, it seems a double-render is needed each time a label content is updated.

在标签组件级别,我需要

At the label component level, I need to

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

然后,在每次重绘时:

  • 根据缓存的边界框进行渲染
  • 比较以前的道具和更新的道具之间的标签内容,以及如果更改的话:
  • 更新并缓存标签边框
  • 根据更新并缓存的边框重新渲染

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

So far, here is how I have implemented my label component:

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来说,双重渲染是一种不寻常的情况吗?

So, my question is not about the algorithm but if there is a better React-compliant way to implement this. Is using the state for caching this sort of slow 'computations' or DOM accesses allowed in the React way? Is double-rendering an unusual case for React?

推荐答案

我个人的观点是,您应该将所有对您重要的状态都放入组件状态.是的,您的建议方法是正确的方法.

My personal opinion is that you should put all state that matters to you into the state of a component. So yes, the way you propose is the right way to do it.

据我所知,双重渲染是获取块大小作为状态的唯一方法,因为需要先绘制块.由于React的性能如此出色,所以这通常没有问题.如果是这样,则可以在子级中对shouldComponentUpdate使用PureRenderMixin或其他检查以确保性能.

As far as I know, double renders are the only way to get the size of a block as state, since the block needs to be drawn first. Since React is so performant, this is usually no problem. if it is, you use PureRenderMixin or other checks on shouldComponentUpdate within the children to ensure performance.

但是请注意,将其编写为mixin可能是明智的做法,因为不要重复自己".

Note however that it might be smart to write this as a mixin, because of "don't repeat yourself".

我经常做响应式SVG,所以我经常需要块元素(svg或html)的x,y宽度和高度.

I do responsive SVG stuff quite frequently so I often need x, y width and height from a block element (svg or html).

我已经编写了一个名为BoundingRectAware的小混合:

I've written this little mixin called 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(),我会实施类似的方法.

within FooComponent, you will automatically get the boundingClientRect as state. I would implement something alike if you use getBBox() in more than one place.

这篇关于使用React.JS检索和缓存SVG节点的边界框的最佳方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆