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.
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