Search code examples
reactjshtml2canvas

I am trying copy the image to canvas using the html2canvas but its not working


I am trying copy the image to canvas using the html2canvas but its not working. I have set up a basic meme generator app which takes image from the user and write top and bottom text and then add the url to the img in the ouput className img but its showing me the white blank screen. Please help me regarding this. Thanks in advance.

import React, { useState } from 'react';

import * as html2canvas from "html2canvas";

import './App.css';

function App() {
  const [uploadImage, setUploadImage] = useState(null);
  const [topText, setTopText] = useState("");
  const [bottomText, setBottomText] = useState("");


  const loadFile = (e) => {
    let imageSrc = URL.createObjectURL(e.target.files[0]);
    setUploadImage(imageSrc)
  }

  const handleSubmit = async (e) => {
    e.preventDefault();
    const uploadContainerRef = document.querySelector(".mainImage");
    const outputRef = document.querySelector(".output");
    html2canvas(uploadContainerRef).then(canvas => {
      const imageData = canvas.toDataURL();
      outputRef.src = imageData;
    })


  }

  return (
    <div className="App">
      <div className="container">
        <div className="text-center font-weight-bold main-heading mb-5">
          <h1 className="display-4">Meme Generator</h1>
        </div>
        <div className="text-center file-image-container">
          <input type="file" accept="image/gif, image/jpeg, image/png" name="image" id="file" onChange={loadFile} />
          <label htmlFor="file" className="btn btn-upload">
          {"Upload your Image Here"}  
          </label>
        </div>
          {
            uploadImage && 
            (
              <div className="uploaded-image-container container" 
                style={{ height: "400px", width: "500px", position: "relative" }}>
                  <div className="topText" style={{
                    fontSize: "3.5rem",
                    fontWeight: "bolder",
                    position: "absolute",
                    color: "white",
                    WebkitTextStroke: "2px black",
                    textAlign: "center",
                    width: "100%"
                  }}>
                     {topText} 
                  </div>
                  <img className="mainImage" style={{height: "25rem", width: "100%"}} src={uploadImage} alt="uploaded"/>
                  <div className="bottomText" style={{
                    fontSize: "3.5rem",
                    fontWeight: "bolder",
                    position: "absolute",
                    bottom: "0",
                    color: "white",
                    WebkitTextStroke: "2px black",
                    textAlign: "center",
                    width: "100%"
                  }}>
                     {bottomText} 
                  </div>
              </div>
            )
          }
          <form onSubmit={handleSubmit}>
            <label htmlFor="topText">top text</label>
            <input type="text" value={topText} onChange={(e) => setTopText(e.target.value)} id="topText"/>
            <label htmlFor="bottomText">bottom text</label>
            <input type="text"  value={bottomText} onChange={(e) => setBottomText(e.target.value)} id="bottomText" />
            <button type="submit" >Create Meme</button>
          </form>


          <img className="output" />
      </div>
    </div>
  );
}

export default App;

Solution

  • You need to set allowTaint to true in html2canvas options. It enables rendering of cross-origin images:

    html2canvas(uploadContainerRef, { allowTaint: true }).then(canvas => {...})
    

    Here are the documentations for all the options: https://html2canvas.hertzen.com/configuration.

    By the way, you should use useRef to access elements generated by React, instead of using querySelector. See these for more info on refs and useRef:

    https://reactjs.org/docs/refs-and-the-dom.html

    https://reactjs.org/docs/hooks-reference.html#useref