Рендеринг объекта холста, полученного от реквизита - PullRequest
0 голосов
/ 19 января 2019

Добрый день!

Я новичок в React и html2canvas. Я делаю приложение, которое будет делать «снимки экрана» моего DOM с использованием html2canvas, а затем сохранять его в массиве снимков экрана, которые затем будут также отображаться на экране.

Я сохраняю каждый объект <canvas>, полученный из обещания html2canvas, в массив, а затем передаю его моему компоненту ScreenshotsContainer, который передает массив компоненту Screenshots. Компонент Screenshots затем сопоставит массив объектов <canvas> с отдельными Screenshot компонентами.

В App.js я вызываю функцию html2canvas и передаю массив компоненту ScreenshotsContainer

import React, { Component } from 'react';
import ScreenshotsContainer from './containers/ScreenshotsContainer/ScreenshotsContainer'
import html2canvas from 'html2canvas';

import './App.css';

class App extends Component {
  state = {
    canvasArray: []
  }

  getScreenshotHandler = () => {
    console.log("[Canvas Array from state length:]" + this.state.canvasArray.length)
    let canvasArray = this.state.canvasArray;

    html2canvas(document.body).then((canvas) => {
      canvasArray.push(canvas)
    });

    console.log("[Canvas Object value: ]" + canvasArray);
    this.setState({ canvasArray: canvasArray })

  }

  render() {

    return (
      <React.Fragment>
        <button onClick={this.getScreenshotHandler}>Get Screenshot</button>
        <ScreenshotsContainer canvasArray={this.state.canvasArray} />
      </React.Fragment>
    );
  }
}

export default App;

Компонент ScreenshotsContainer передаст полученный массив в компонент Screenshots:

    import React, { Component } from 'react';
import './ScreenshotsContainer.css'
import Screenshots from '../../components/Screenshots/Screenshots';

class ScreenshotsContainer extends Component {

    render() {
        return (
            <div className="ScreenshotsContainer">
                <Screenshots canvasArray={this.props.canvasArray} />
            </div>
        );
    }
}
export default ScreenshotsContainer;

Компонент Screenshots отобразит массив и передаст каждый объект canvas в компонент Screenshot:

import React, { Component } from 'react';
import Screenshot from './Screenshot/Screenshot';

class Screenshots extends Component {
    render() {
        const screenshots = this.props.canvasArray.map(canvas => {
            return (
                <Screenshot
                    key={Math.random}
                    canvasObj={canvas}
                />
            )
        })
        return (
            <React.Fragment>
                {screenshots}
            </React.Fragment>
        );
    }
}
export default Screenshots;

Вот компонент Screenshot

import React from 'react';
import './Screenshot.css';

const screenshot = (props) => (
    <div className="Screenshot" >
        <canvas ref={props.canvasObj} style={{
            width: '10%',
            height: '10%'
        }} />
    </div>
);

export default screenshot;

Что я на самом деле получаю, нажимая кнопку:

Актуальный скриншот моего результата Мне было интересно, какая часть пошла не так. Любая помощь будет оценена.

1 Ответ

0 голосов
/ 23 января 2019

Эта конкретная библиотека работает особым образом (похоже, она делает много «волшебства» под капотом - вы должны взглянуть на исходный код здесь , более конкретно, на папку рендерера внутри src)

Сохранение холста в состоянии внутри массива (правильный способ реагирования на действия) будет проблемой, поскольку он сохраняет его как сложный объект со многими методами и т. Д. ... и мы не можем визуализировать объекты ... Эта библиотека не была написана с учетом React ...

Пример кода ниже представляет собой простую реализацию в React ...

Вот живая демонстрация: https://codesandbox.io/s/9y24vwn1py

import React, { Component } from 'react';
import html2canvas from 'html2canvas';

class App extends Component {
  constructor(props) {
    super(props);
    this.captureRef = React.createRef();
    this.displayRef = React.createRef();
  }

  getScreenshotHandler = () => {
    html2canvas(this.captureRef.current).then(canvas =>
      this.displayRef.current.appendChild(canvas),
    );
  };

  render() {
    return (
      <div>
        <div ref={this.captureRef}>
          <h2>This enitre div will be captured and added to the screen</h2>
        </div>
        <button onClick={this.getScreenshotHandler}>Get Screenshot!</button>
        <section>
          <h5>Your screenshots will be availbale below</h5>
          <div ref={this.displayRef} />
        </section>
      </div>
    );
  }
}

export default App;

РЕДАКТИРОВАТЬ: на основе комментария ниже здесь еще один обходной путь:

class App extends Component {
  constructor(props) {
    super(props);
    this.state = { canvasArray: [] };
    this.captureRef = React.createRef();
  }

  getScreenshotHandler = () => {
    html2canvas(this.captureRef.current).then(canvas =>
      this.setState({
        canvasArray: [canvas.toDataURL(), ...this.state.canvasArray],
      }),
    );
  };

  renderCanvas = () => {
    return this.state.canvasArray.map((canvas, i) => {
      return <img key={i} src={canvas} alt="screenshot" />;
    });
  };

  render() {
    return (
      <div className="wrapper">
        <div ref={this.captureRef}>
          <p>This enitre div will be captured</p>
        </div>
        <button onClick={this.getScreenshotHandler}>Get Screenshot!</button>
        <section>
          <h5>Your screenshots will be availbale below:</h5>
          {this.renderCanvas()}
        </section>
      </div>
    );
  }
}

Ссылка на демо: https://codesandbox.io/s/1r213057vq

...