From 5b56c4e3fc7297f80fa23793edf822ac7a9400d2 Mon Sep 17 00:00:00 2001 From: Fahmi Bnchi <77180905+bnchi@users.noreply.github.com> Date: Sat, 17 Dec 2022 13:00:33 +0300 Subject: [PATCH] [CreateMeme] Add Basic functionalities (#82) * Add Basic Meme Tool * Multiple Render Fix Co-authored-by: Fahmi Bnchi --- src/App.tsx | 4 + src/CreateMeme/CreateMeme.tsx | 142 ++++++++++++++++++++++++++++++++++ src/ToolsNav/ToolsNav.tsx | 17 ++-- 3 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 src/CreateMeme/CreateMeme.tsx diff --git a/src/App.tsx b/src/App.tsx index 7a280ec..77cac2a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import workerContent from './pdfjs.worker.min.json'; import QuickSignPDF from './QuickSignPDF/QuickSignPDF'; import SplitPDF from './SplitPDF/SplitPDF'; import ToolsNav from './ToolsNav/ToolsNav'; +import CreateMeme from './CreateMeme/CreateMeme'; const workerBlob = new Blob([workerContent], { type: 'text/javascript' }); const workerBlobURL = URL.createObjectURL(workerBlob); @@ -47,6 +48,9 @@ export const App = (): JSX.Element => { + + +
diff --git a/src/CreateMeme/CreateMeme.tsx b/src/CreateMeme/CreateMeme.tsx new file mode 100644 index 0000000..adb1439 --- /dev/null +++ b/src/CreateMeme/CreateMeme.tsx @@ -0,0 +1,142 @@ +import { useCallback, useState, useEffect } from 'react'; +import UploadButton from '../components/UploadButton'; +import { fabric } from 'fabric'; // this also installed on your project +import { useFabricJSEditor, FabricJSCanvas } from 'fabricjs-react'; + +const MEME_TEXT_SHADOW = new fabric.Shadow({ + color: 'black', + blur: 15, +}); + +let wasImageLoadedToCanvas = false; + +const CreateMeme = (): JSX.Element => { + const { editor, onReady } = useFabricJSEditor(); + const [imagePath, setImagePath] = useState(null); + const [fileName, setFileName] = useState( + `new-meme-${new Date().getTime()}.png` + ); + + const onDrop = useCallback( + async (files) => { + wasImageLoadedToCanvas = false; + if (files.length === 0 || files.length > 1) return; + setImagePath(URL.createObjectURL(files[0])); + }, + [editor] + ); + + useEffect(() => { + if (!imagePath || wasImageLoadedToCanvas || !editor) return; + editor?.deleteAll(); + wasImageLoadedToCanvas = true; + fabric.Image.fromURL( + imagePath, + function (oImg: any) { + const aspectRatio = oImg.width / oImg.height; + const width = 600; + const height = width / aspectRatio; + oImg.scaleToWidth(width); + oImg.scaleToHeight(height); + editor?.canvas.setDimensions({ + width: width, + height: height, + }); + editor?.canvas.add(oImg); + }, + { + selectable: false, + hasControls: false, + lockMovementX: true, + lockMovementY: true, + } + ); + }, [imagePath, fabric, editor]); + + const onSave = useCallback(async () => { + if (!imagePath || !editor) return; + saveAs( + editor.canvas.toDataURL({ format: 'png' }), + fileName.endsWith('.png') ? fileName : `${fileName}.png` + ); + }, [imagePath, editor, fileName]); + + return ( +
+
+ {!imagePath && ( +
+
+ +
+
+ )} + {imagePath && ( +
+ {/* Toolbar */} +
+
+ + Create New Meme + +
+
+ +
+
+ +
+
+
+ +
+
+ setFileName(e.target.value)} + type="text" + className="flex-grow h-10 py-0 mr-2 lg:mr-5 px-2 lg:px-5 border-gray-300 placeholder-gray-200 leading-0 lg:leading-3 focus:ring-green-700 lg:max-w-sm" + placeholder="name-your-meme.png" + /> + +
+
+ )} +
+
+ ); +}; + +export default CreateMeme; diff --git a/src/ToolsNav/ToolsNav.tsx b/src/ToolsNav/ToolsNav.tsx index c1b05a3..01e5840 100644 --- a/src/ToolsNav/ToolsNav.tsx +++ b/src/ToolsNav/ToolsNav.tsx @@ -74,6 +74,14 @@ const ToolsNav = ({ > Bulk-Edit Photos + + Create Meme + {showTodo && ( <> TODO{' '} Make GIF - - TODO{' '} - Create Meme - )}