Извлечение URL данных изображения после обработки текста на холсте и показ результата в CardMedia Material-UI - PullRequest
0 голосов
/ 05 июля 2019

Я работаю через следующий код, размещенный в песочнице здесь

import React, { useEffect, useRef } from "react";
import ReactDOM from "react-dom";
import backImg from "./background.png";

const Canvas = props => {
  const canvas = useRef(null);

  const image = useRef(null);
  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    image.current.onload = () => {
      ctx.drawImage(image.current, 0, 0);
      ctx.font = "40px Courier";
      ctx.fillText(props.text, 210, 75);
    };
  }, []);
  useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    ctx.drawImage(image.current, 0, 0);
    ctx.font = "40px Courier";
    ctx.fillText(props.text, 210, 75);
  });
  return (
    <div>
      <canvas ref={canvas} width={640} height={425} />
      <img
        ref={image}
        alt="Stackoverflow56203352"
        src={backImg}
        className="hidden"
      />
    </div>
  );
};

function App() {
  return (
    <div className="App">
      <Canvas text="TEST 123" />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Я не уверен, как извлечь URL изображения после того, как текст был внедрен в изображение.то есть в моем случае я хочу URL изображения с текстом на нем.

И я хочу, чтобы изображение отображалось в компоненте CardMedia пользовательского интерфейса.

1 Ответ

1 голос
/ 08 июля 2019

Вы можете экспортировать Canvas в URL данных с помощью метода HTMLCanvasElement.toDataURL () .

Примерно так:

    useEffect(() => {
        const ctx = canvas.current.getContext("2d");
        ctx.drawImage(image.current, 0, 0);
        ctx.font = "40px Courier";
        ctx.fillText(props.text, 210, 75);
        const imgUrl = canvas.current.toDataURL("image/jpeg");
  });

Но изображение должно бытьподается из того же источника, в противном случае вы получите эту ошибку (которая происходит в вашей песочнице):

Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

Ресурс об этой ошибке и о том, как с ней справиться

Рабочий пример ниже (я использовал изображение, размещенное на Facebook, потому что они, как говорят, поддерживают такую ​​вещь и показывают, что ошибка исчезла, когда изображение того же источника, разрешающего происхождения иликогда у него есть атрибут crossOrigin="anonymous", откройте вывод консоли на новой вкладке, чтобы увидеть результат, так как запрос OP, результат отображается в CardMedia из MarterialUI):

const backImg = "https://scontent-cdg2-1.xx.fbcdn.net/v/t1.0-9/26907788_1614183255284072_4356465325754439623_n.jpg?_nc_cat=102&_nc_oc=AQle2ac8QeR7C5HY-Z9oxWXbMdzjkDlVo8WYfhqDZArSYoEb1q1Xv5ZaE1Z4JNm7bmY&_nc_ht=scontent-cdg2-1.xx&oh=1c12333fe33d7d3fc2e39d3794d7dab4&oe=5DC018D1";

const { CardMedia } = MaterialUI;

const Canvas = props => {
  const [finalSrc, setFinalSrc] = React.useState(null)
  const canvas = React.useRef(null);

  const image = React.useRef(null);
  React.useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    image.current.onload = () => {
      ctx.drawImage(image.current, 0, 0);
      ctx.font = "40px Courier";
      ctx.fillText(props.text, 210, 75);
    };
  }, []);
  React.useEffect(() => {
    const ctx = canvas.current.getContext("2d");
    ctx.drawImage(image.current, 0, 0);
    ctx.font = "40px Courier";
    ctx.fillText(props.text, 210, 75);
    setFinalSrc(canvas.current.toDataURL("image/jpeg"));
    
  });
  return (
    <div>
      {finalSrc && <CardMedia image={finalSrc} style={{ height: 425, width: 640 }} />}
      <canvas ref={canvas} width={640} height={425} className="hidden" />
      <img
        ref={image}
        alt="Stackoverflow56203352"
        src={backImg}
        className="hidden"
        crossOrigin="anonymous"
      />
    </div>
  );
};

function App() {
  return (
    <div className="App">
      <Canvas text="TEST 123" />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
.hidden {
  visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@material-ui/core@latest/umd/material-ui.development.js" crossorigin="anonymous"></script>
<div id="root"></div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...