在画布上进行文本操作后提取图像数据URL,并在Material-UI的CardMedia中显示结果



我正在通过以下在Sandbox托管的代码

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带有文本。

我希望图像显示在材料 - UI的CardMedia组件中。

您可以使用htmlcanvaselement.todataurl((方法将画布导出到数据URL。

喜欢:

    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,在Marterialui的CardMedia中显示了结果:

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>

最新更新