在画布上进行文本处理之后提取图像数据url,并在Material-UI的CardMedia中显示结果

时间:2019-07-05 16:08:45

标签: reactjs html5-canvas material-ui

我正在研究托管在沙箱here上的以下代码

this.introService.setOptions(...)

我不确定在文本上实现文本后如何提取图像的url。也就是说,在我的情况下,我希望图像上带有文字的网址。

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

1 个答案:

答案 0 :(得分:1)

您可以使用HTMLCanvasElement.toDataURL()方法将Canvas导出到数据网址。

像这样:

    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.

Resource about this error and how to deal with it

下面的工作示例(我使用了由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>