使用canvas对象更新react组件中的状态失败

时间:2017-12-04 18:13:22

标签: reactjs canvas state

我们在世界地图上有一些区域会突出显示用户将鼠标放在该区域上的时间。我解决这个问题的方法是使用canvas元素并在区域周围绘制粗糙多边形,并使用一些MIT代码检测用户是否将鼠标放在多边形内。如果他们这样做,那么图像将切换到显示突出显示和标记区域的相应图形。

一切似乎都没事,但是当我试图改变状态时,它会爆炸。我认为它与某个地方的虚拟dom有关。

这是组件

class HomeMap extends Component {
    constructor(props) {
        super(props);
        this.onMouseMove = this.onMouseMove.bind(this);
        this.state = {
            placeName: 'default',
        };
    }

    onMouseMove(canvas, eX, eY) {
        const { top, left } = canvas.getBoundingClientRect();
        const [x, y] = [eX - left, eY - top];
        const mouseOver = mapImages.map(image => ({
            ...image,
            isInside: inside([x, y], image.polygon),
        }))
            .filter(({ isInside }) => isInside);

        const stateChange = {
            placeName: mouseOver.length === 0
                ? 'default'
                : mouseOver[0].name,
        };
        console.log(stateChange);
        this.setState(stateChange);
    }

    componentDidMount() {
        this.ctx.drawImage(getImage('default').image, 0, 0, 656, 327);
    }

    componentDidUpdate() {
        console.log(getImage('default'))
        console.log(this.state);
        this.ctx.drawImage(getImage(this.state.placeName).image, 0, 0, 656, 327);
    }

    render() {
        return (
            <div>
                <canvas 
                    onMouseMove={(e) => { this.onMouseMove(this.canvas, e.clientX, e.clientY); } }
                    width={626}
                    height={327}
                    ref={(ref) => {
                        this.ctx = ref.getContext('2d');
                        this.canvas = ref;
                    } }
                />
            </div>
        );
    }
};

here is a fairly minimal reproduction running on codesandbox

当我在生产中运行它时,当组件更新时,画布ref变为null,我相信这就是抛出错误。

1 个答案:

答案 0 :(得分:0)

我找到问题的原因:缓存2d上下文。

<canvas 
    onMouseMove={(e) => { this.onMouseMove(this.canvas, e.clientX, e.clientY); } }
    width={626}
    height={327}
    ref={(ref) => {
        this.ctx = ref.getContext('2d'); // <=== remove this
        this.canvas = ref;
    } }
/>

因此,当我需要访问绘图函数时,我只是缓存了canvas元素并调用了canvas.getContext('2d'),而不是保存对getContext的引用。