Created
December 19, 2023 04:45
-
-
Save 0xN1/47b20fb998aff482cf06884dea32643c to your computer and use it in GitHub Desktop.
cari-orang meme generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use client"; | |
import { useEffect, useState, useRef } from "react"; | |
import { useDropzone } from "react-dropzone"; | |
import Draggable from "react-draggable"; | |
import { useScreenshot } from "use-react-screenshot"; | |
type Props = {}; | |
const MemeGeneratorPage = (props: Props) => { | |
const mainRef = useRef(null); | |
const [image, takeScreenshot] = useScreenshot(); | |
const [text, setText] = useState("cari meme"); | |
const [textColor, setTextColor] = useState("#111111"); | |
const [bgColor, setBgColor] = useState("#eeeeee"); | |
const [showMenu, setShowMenu] = useState(false); | |
const takePicture = () => { | |
takeScreenshot(mainRef.current); | |
}; | |
const downloadImage = () => { | |
const link = document.createElement("a"); | |
link.href = image; | |
link.download = "screenshot.png"; | |
document.body.appendChild(link); | |
link.click(); | |
document.body.removeChild(link); | |
}; | |
const { acceptedFiles, getRootProps, getInputProps } = useDropzone({ | |
noClick: true, | |
}); | |
const [imageFiles, setImageFiles] = useState<{ | |
[key: string]: { | |
name: string; | |
url: string; | |
}; | |
}>({}); | |
useEffect(() => { | |
acceptedFiles.map((file) => { | |
// get image as base64 | |
const reader = new FileReader(); | |
reader.readAsDataURL(file); | |
reader.onload = () => { | |
setImageFiles({ | |
...imageFiles, | |
[file.name]: { | |
name: file.name, | |
url: reader.result as string, | |
}, | |
}); | |
}; | |
}); | |
}, [acceptedFiles]); | |
return ( | |
<> | |
<div | |
ref={mainRef} | |
style={{ backgroundColor: bgColor }} | |
className="min-h-screen w-full overflow-hidden flex items-center justify-center flex-col" | |
> | |
<div | |
{...getRootProps({ | |
className: | |
"dropzone w-full h-full flex items-center justify-center flex-col text-white font-bold text-2xl relative", | |
})} | |
> | |
<div className="absolute inset-0 flex items-center justify-center"> | |
<Draggable> | |
<span | |
style={{ | |
color: textColor, | |
}} | |
className="text-8xl break-words mx-4 sm:mx-0 sm:text-9xl font-bold text-zinc-800 z-[1] -mt-20 cursor-move" | |
> | |
{text} | |
</span> | |
</Draggable> | |
</div> | |
{/* <input {...getInputProps()} /> */} | |
<div className="drag-area w-full min-h-screen flex items-center justify-center z-[0]"> | |
{imageFiles && | |
Object.keys(imageFiles).map((key) => { | |
return ( | |
<Draggable key={key}> | |
<img | |
draggable={false} | |
src={imageFiles[key]?.url} | |
alt={imageFiles[key]?.name} | |
className="w-[50vh] h-auto object-cover cursor-move" | |
/> | |
</Draggable> | |
); | |
})} | |
</div> | |
<span className="absolute text-zinc-500 bottom-8 font-normal font-primary text-sm sm:text-xl"> | |
cari-orang.com | |
</span> | |
</div> | |
<span></span> | |
</div> | |
<div className="fixed top-8 left-8 w-max h-auto text-zinc-800 font-primary flex z-[3]"> | |
<button onClick={() => setShowMenu(!showMenu)} className=""> | |
toolbar | |
</button> | |
</div> | |
{showMenu && ( | |
<div className="bg-zinc-800/80 min-h-40 sm:max-h-40 backdrop-blur-2xl py-4 fixed bottom-0 px-0 sm:px-16 w-full sm:min-h-[10vh] flex flex-col sm:gap-0 gap-2 sm:flex-row items-center justify-between text-white z-10 rounded-t-2xl"> | |
<div className="w-full flex flex-col sm:flex-row gap-4 py-2 mx-4 sm:mx-0 items-center justify-center"> | |
<input | |
onChange={(e) => setText(e.target.value)} | |
type="text" | |
placeholder="type sini..." | |
maxLength={18} | |
className="border-zinc-700 text-zinc-200 border-2 | |
text-lg sm:text-2xl w-max px-4 py-2 bg-transparent outline-none focus:outline-none active:bg-zinc-300 rounded-xl shadow-lg" | |
/> | |
<div className="flex flex-row w-full gap-2 items-center justify-center"> | |
<input | |
onChange={(e) => setTextColor(e.target.value)} | |
type="text" | |
placeholder="#222222" | |
className="w-1/3 border-zinc-700 text-zinc-200 border-2 | |
text-lg sm:text-2xl px-4 py-2 bg-transparent outline-none focus:outline-none active:bg-zinc-300 rounded-xl shadow-lg" | |
/> | |
<input | |
onChange={(e) => setBgColor(e.target.value)} | |
type="text" | |
placeholder="#EEEEEE" | |
className="w-1/3 border-zinc-700 text-zinc-200 border-2 | |
text-lg sm:text-2xl px-4 py-2 bg-transparent outline-none focus:outline-none active:bg-zinc-300 rounded-xl shadow-lg" | |
/> | |
</div> | |
</div> | |
<div className="flex flex-row gap-4 items-center justify-center"> | |
{image ? ( | |
<> | |
<button> | |
<div | |
onClick={downloadImage} | |
className="flex items-center font-primary justify-center border-zinc-700 text-zinc-300 border-2 text-2xl px-4 py-2 rounded-xl shadow-lg" | |
> | |
SAVE | |
</div> | |
</button> | |
<button> | |
<div | |
onClick={() => { | |
// refresh page | |
window.location.reload(); | |
}} | |
className="flex items-center font-primary justify-center border-zinc-700 text-zinc-300 border-2 text-2xl px-4 py-2 rounded-xl shadow-lg" | |
> | |
RESET | |
</div> | |
</button> | |
</> | |
) : ( | |
<button> | |
<div | |
onClick={takePicture} | |
className="flex items-center font-primary justify-center border-zinc-700 text-zinc-300 border-2 text-2xl px-4 py-2 rounded-xl shadow-lg" | |
> | |
SCREENSHOT | |
</div> | |
</button> | |
)} | |
</div> | |
{image && ( | |
<img | |
src={image} | |
alt="Screenshot" | |
className="h-40 object-contain w-40 p-4" | |
/> | |
)} | |
</div> | |
)} | |
</> | |
); | |
}; | |
export default MemeGeneratorPage; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment