1/**
2 * This meme creation tool app will allow users to create memes by selecting an image and adding top and bottom text.
3 * We'll use HTML5 Canvas to render the meme directly in the browser, with custom positioning for different meme templates.
4 */
35 }, []);
36
37 const getTextPositions = (imageWidth: number, imageHeight: number, templateId: string): [TextPosition, TextPosition] => {
38 const defaultColor = "white";
39 switch (templateId) {
40 case "1": // Drake
41 return [
42 { x: imageWidth * 0.7, y: imageHeight * 0.25, maxWidth: imageWidth * 0.5, color: "black" },
43 { x: imageWidth * 0.7, y: imageHeight * 0.75, maxWidth: imageWidth * 0.5, color: "black" }
44 ];
45 case "2": // Distracted Boyfriend
46 return [
47 { x: imageWidth * 0.6, y: imageHeight * 0.1, maxWidth: imageWidth * 0.3, color: defaultColor },
48 { x: imageWidth * 0.8, y: imageHeight * 0.1, maxWidth: imageWidth * 0.3, color: defaultColor }
49 ];
50 case "3": // Two Buttons
51 return [
52 { x: imageWidth * 0.5, y: imageHeight * 0.1, maxWidth: imageWidth * 0.8, color: defaultColor },
53 { x: imageWidth * 0.5, y: imageHeight * 0.9, maxWidth: imageWidth * 0.8, color: defaultColor }
54 ];
55 case "4": // Expanding Brain
56 return [
57 { x: imageWidth * 0.5, y: imageHeight * 0.15, maxWidth: imageWidth * 0.8, color: defaultColor },
58 { x: imageWidth * 0.5, y: imageHeight * 0.95, maxWidth: imageWidth * 0.8, color: defaultColor }
59 ];
60 case "5": // Change My Mind
61 return [
62 { x: imageWidth * 0.5, y: imageHeight * 0.7, maxWidth: imageWidth * 0.8, color: defaultColor },
63 { x: imageWidth * 0.5, y: imageHeight * 0.9, maxWidth: imageWidth * 0.8, color: defaultColor }
64 ];
65 default:
66 return [
67 { x: imageWidth * 0.5, y: imageHeight * 0.1, maxWidth: imageWidth * 0.9, color: defaultColor },
68 { x: imageWidth * 0.5, y: imageHeight * 0.9, maxWidth: imageWidth * 0.9, color: defaultColor }
69 ];
70 }
78 if (!ctx) return;
79
80 const selectedImage = templates.find(t => t.id === selectedTemplate);
81 if (!selectedImage) return;
82
83 const image = new Image();
84 image.crossOrigin = "anonymous";
85 image.onload = () => {
86 canvas.width = image.width;
87 canvas.height = image.height;
88 ctx.drawImage(image, 0, 0);
89
90 const fontSize = Math.floor(image.height / 15);
91 ctx.font = `bold ${fontSize}px Impact, sans-serif`;
92 ctx.textAlign = "center";
93
94 const [topPosition, bottomPosition] = getTextPositions(image.width, image.height, selectedTemplate);
95
96 // Function to draw text with word wrap
131 setMemeUrl(canvas.toDataURL());
132 };
133 image.src = selectedImage.url;
134 };
135
164 </form>
165 <canvas ref={canvasRef} style={{ display: 'none' }}></canvas>
166 {memeUrl && <img src={memeUrl} alt="Generated Meme" className="meme-image" />}
167 <p>
168 <a href={import.meta.url.replace("esm.town", "val.town")} target="_blank">View Source</a>
247 background-color: #45a049;
248 }
249 .meme-image {
250 max-width: 100%;
251 display: block;