Home > Software design >  ReactJS elements not converting to canvas properly using html2canvas?
ReactJS elements not converting to canvas properly using html2canvas?

Time:09-20

I have built a meme generator app - My App Image

I am using html2canvas to convert my meme image, top text and bottom text to canvas and then I can download the canvas.

download.js

import html2canvas from "html2canvas";

const download = async (capturedData) => {
    console.log(capturedData); //example- this line of code gives below commented data in console 
    /*<div  id="capture">
        <p >world</p>
        <p >Hello</p>
        <img  src="https://i.imgflip.com/1o00in.jpg" alt="Broken Meme Image">
      </div>*/

    const canvas = await html2canvas(capturedData);
    const imgUrl = canvas.toDataURL("image/png", 1.0 );

    if(window.navigator.msSaveBlob) {// this will only true in IE browser
        ieDownload(canvas);
    }else{
        basicBrowserDownload(imgUrl);
    }
}



function basicBrowserDownload(imgUrl) {
    const a = window.document.createElement('a');
    a.style = 'display:none';
    a.download = 'Meme.png';
    a.href = imgUrl;
    document.body.appendChild(a);

    a.click();

    document.body.removeChild(a);
    a.remove();
}

function ieDownload(canvas) {
    window.navigator.msSaveBlob(canvas.msToBlob(), 'Meme.png');
}

export default download;

Showcase.js

import React, { useRef } from "react";
import download from "../download";

export default function Showcase() {
  const captureRef = useRef();

  const [meme, setMeme] = React.useState({
    topText: "",
    bottomText: "",
    randomImgUrl: "https://i.imgflip.com/af002.jpg",
  });

  const [allMeme, setAllMeme] = React.useState([]);

  React.useEffect(() => {
    fetch("https://api.imgflip.com/get_memes")
      .then((res) => res.json())
      .then((bigData) => {
        // it will setAllMeme to array of 100 meme objects
        setAllMeme(bigData.data.memes);
      });
  }, []);

  function handleChange(event) {
    let { name, value } = event.target;
    setMeme((prevState) => ({ ...prevState, [name]: value }));
  }

  function getRandomImg() {
    let randomNum = Math.floor(Math.random() * 100);
    let randomUrl = allMeme[randomNum].url;
    setMeme((prevState) => ({ ...prevState, randomImgUrl: randomUrl }));
  }

  return (
    <section className="showcase">
      <div className="user-interactions">
        <div>

          <div className="input-field">
            <input
              type="text"
              name="topText"
              value={meme.topText}
              onChange={handleChange}
              placeholder="Top Text"
            />
            <input
              type="text"
              name="bottomText"
              value={meme.bottomText}
              onChange={handleChange}
              placeholder="Bottom Text"
            />
          </div>

          <button onClick={getRandomImg} className="generate-img-btn">
            Give me a New Image !
          </button>
         
          <button onClick={() => download(captureRef.current)} className="generate-img-btn">
            Download Meme
          </button>
        </div>
      </div>

      <div className="meme-items" id="capture"
        ref={captureRef} >
        <p className="top-text">{meme.topText}</p>
        <p className="bottom-text">{meme.bottomText}</p>
        <img
          className="meme-img"
          src={meme.randomImgUrl}
          alt="Broken Meme Image"
        />
      </div>
    </section>
  );
}

but I am using an API to load random image for meme. I think html2canvas is not supporting it that's why I am only getting top text and bottom text after downloading.

downloaded image sample

However, this method is working well when I replaced the random image from API to local saved image.

Can you please tell me the solution?

CodePudding user response:

You can use :

html2canvas(capturedDate, {allowTaint: true, useCORS: true, logging: true})

See this comment to the same issue from the html2canvas repository: https://github.com/niklasvh/html2canvas/issues/722#issuecomment-487279018

From the docs:

allowTaint: Whether to allow cross-origin images to taint the canvas useCors: attempt to load images from a server using CORS logging: Enable logging for debug purposes

  • Related