Skip to content

Instantly share code, notes, and snippets.

@0xN1
Created December 19, 2023 04:45
Show Gist options
  • Save 0xN1/47b20fb998aff482cf06884dea32643c to your computer and use it in GitHub Desktop.
Save 0xN1/47b20fb998aff482cf06884dea32643c to your computer and use it in GitHub Desktop.
cari-orang meme generator
"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