Рендеринг/возврат холста HTML5 в ReactJS

Я пытаюсь сделать холст с помощью React. Графика внутри холста также будет обрабатываться с помощью метода Reacts render.

В текущем коде выполняется визуализация холста с графикой, которую я хочу. Но я ищу способ вернуть холст с моей графикой из метода render. Причина, по которой я хочу это, - это то, что я хочу, чтобы это работало в "Реагировать".

В идеале я бы хотел, чтобы мой код был примерно таким:

return(
  <div>
    <canvas id='my_canvas_with_graphics_rendered_in_react'></canvas>
  </div>
);

Во-первых, я хочу знать, возможно ли это. Или я должен искать альтернативу.

Возможно, я пропустил пункт "Реакт", если это так, пожалуйста, дайте мне знать. Надеюсь, что есть решение, потому что из того, что я прочитал, React рекламирует себя как V в MVC. Вот почему, если это возможно, это было бы идеальным решением для того, что я пытаюсь сделать. Мне не пришлось бы беспокоиться об рендеринге внутри моего холста. Я просто предоставил данные компоненту, и React повторно изменил бы эти изменения.

Я отмечен в инструкции return, где я считаю, что правильный код должен идти.

Код HTML:

<div id='wrapper'>
    <canvas id='canvas'></canvas>
</div>

Код jsx:

var MyCanvas = React.createClass({
    render:function(){
        var line = this.props.lines;
        var ctx = this.props.canvas.getContext("2d");

        ctx.strokeStyle = 'rgba(0,0,0,0.5)';
        ctx.beginPath();
        ctx.moveTo(line[0].x0, line[0].y0);
        // .... more code .....
        ctx.stroke();

        return(
            <div>
                /* *********************************
                ??? RETURN MY RENDERED CANVAS
                    WITH GRAPHIC LINES. ????
             This is where I want to return the canvas 
                *********************************  */
            </div>
        );

    }
});


var wrapper = document.getElementById('wrapper');
var canvas = document.getElementById('canvas');
var line1 = { x0: 0, y0: 10, x1: 20, y1: 30 };
var line2 = { x0: 40, y0: 50, x1: 60, y1: 70 };

var myCanvas = <MyCanvas canvas={ canvas } lines={ [line1, line2] } />;
React.render(myCanvas, wrapper);

Надеюсь, я поняла.

Ответы

Ответ 1

Ваша единственная ошибка в том, что вы не знакомы с реакциями ref. попробуйте следующее:

class ConnectionChart extends React.Component {

    componentDidMount() {
        let canvas = ReactDOM.findDOMNode(this.refs.myCanvas);
        let ctx = canvas.getContext('2d');

        ctx.fillStyle = 'rgb(200,0,0)';
        ctx.fillRect(10, 10, 55, 50);
    }

    render() {
        return (
            <div>
                <canvas ref="myCanvas" />
            </div>
        );
    }
}

Возможно, вы избавились от стиля ES6, но вы поняли эту идею. Из-за того, что u может рисовать и другими методами ^ ^

Ответ 2

Вместо использования canvas в вашем методе render вы сделаете что-то вроде этого:

var MyCanvas = React.createClass({
  componentDidMount: function () {
    React.getDOMNode(this).appendChild(this.props.canvas);
  },
  render: function() {
    return <div />;
  }
});

Вы просто визуализируете пустой div и ждете, пока React не смонтирует это. Когда вы монтируете, вы добавляете свой холст к фактическому DOM node, созданному React.

Причиной этого является то, что метод render возвращает только виртуальные узлы DOM, которые React затем переводит на реальные узлы DOM. И поскольку у вас есть реальный DOM node, вы не можете преобразовать его в виртуальный node. Другая причина заключается в том, что вы должны возвращать только узлы из render, которые управляют элементами React. И поскольку вы управляете холстом из-за контроля Reacts, вы должны использовать реальный DOM apis, чтобы управлять им.

Ответ 3

Ключ переопределяет правильные методы жизненного цикла React для рисования. Метод render создает элемент DOM холста, и вы можете добавить обратный вызов refs, чтобы установить ссылку на него, но вам нужно подождать, пока компонент не будет смонтирован для рисования на холсте.

Вот пример, в котором используется обратный вызов, как рекомендуют рекомендации React. Он предназначен для визуализации статического (неанимированного) графического компонента на основе реквизита и обновлений при изменении реквизита. Он также подписывается на событие изменения размера окна, чтобы его можно было динамически масштабировать с помощью CSS (например, width: 100%). Этот пример основан на коде из этого Gist.

export default class CanvasComponent extends React.Component {

    constructor(props) {
        super(props);

        this._resizeHandler = () => {
            /* Allows CSS to determine size of canvas */
            this.canvas.width = this.canvas.clientWidth;
            this.canvas.height = this.canvas.clientHeight;

            this.clearAndDraw();
        }
    }

    componentDidMount() {
        window.addEventListener('resize', this._resizeHandler);

        /* Allows CSS to determine size of canvas */
        this.canvas.width = this.canvas.clientWidth;
        this.canvas.height = this.canvas.clientHeight;

        this.clearAndDraw();
    }

    componentWillUnmount() {
        window.removeEventListener('resize', this._resizeHandler);
    }

    componentDidUpdate(prevProps, prevState) {
        if (this.props.secondRect !== prevProps.secondRect) {
            this.clearAndDraw();
        }
    }

    clearAndDraw() {
        const ctx = this.canvas.getContext('2d');
        if (ctx) {
            ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
            this.draw(ctx);
        }
    }

    draw(ctx) {
        ctx.fillStyle = 'rgb(200, 0, 0)';
        ctx.fillRect(10, 10, 50, 50);

        if (this.props.secondRect) {
            ctx.fillStyle = 'rgba(0, 0, 200, 0.5)';
            ctx.fillRect(30, 30, 50, 50);
        }
    }

    render() {
        return (
            <canvas ref={canvas => this.canvas = canvas} />
        );
    }
}

Вы можете установить опору secondRect из родительского компонента или установить его из состояния, чтобы увидеть обновление компонента при обновлении prop. Вы можете расширить эту идею, чтобы создать какой-либо обработчик данных, управляемый данными, например диаграмму или график.