Web-based Meme Generator JavaScript, Canvas
👤 Sharing: AI
```javascript
<!DOCTYPE html>
<html>
<head>
<title>Web-based Meme Generator</title>
<style>
body {
font-family: sans-serif;
text-align: center;
}
#memeCanvas {
border: 1px solid black;
margin-bottom: 10px;
}
.controls {
margin-bottom: 20px;
}
.controls label {
display: block;
margin-bottom: 5px;
}
.controls input,
.controls textarea {
width: 300px;
margin-bottom: 10px;
padding: 5px;
}
.controls button {
padding: 8px 15px;
background-color: #4CAF50;
color: white;
border: none;
cursor: pointer;
}
.controls button:hover {
background-color: #3e8e41;
}
</style>
</head>
<body>
<h1>Meme Generator</h1>
<canvas id="memeCanvas" width="500" height="400"></canvas>
<div class="controls">
<label for="imageInput">Image URL:</label>
<input type="text" id="imageInput" placeholder="Enter image URL">
<label for="topText">Top Text:</label>
<input type="text" id="topText" placeholder="Enter top text">
<label for="bottomText">Bottom Text:</label>
<input type="text" id="bottomText" placeholder="Enter bottom text">
<button id="generateButton">Generate Meme</button>
</div>
<script>
// Get references to the canvas and input elements
const canvas = document.getElementById('memeCanvas');
const ctx = canvas.getContext('2d'); // Get the 2D rendering context
const imageInput = document.getElementById('imageInput');
const topTextInput = document.getElementById('topText');
const bottomTextInput = document.getElementById('bottomText');
const generateButton = document.getElementById('generateButton');
let image = new Image(); // Create a new image object
image.crossOrigin = "anonymous"; // Required for images from different domains
let imageLoaded = false;
// Function to draw the meme on the canvas
function drawMeme() {
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
// Draw the image if it's loaded
if (imageLoaded) {
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
} else {
// Optionally, display a placeholder message if the image isn't loaded yet
ctx.font = '20px sans-serif';
ctx.fillStyle = 'black';
ctx.textAlign = 'center';
ctx.fillText('Loading Image...', canvas.width / 2, canvas.height / 2);
}
// Set text properties
ctx.font = '30px Impact'; //Classic Meme Font
ctx.fillStyle = 'white';
ctx.strokeStyle = 'black'; // Outline for better readability
ctx.textAlign = 'center';
ctx.lineWidth = 2; // Outline thickness
// Get the top and bottom text from the input fields
const topText = topTextInput.value.toUpperCase();
const bottomText = bottomTextInput.value.toUpperCase();
// Draw the top text
ctx.fillText(topText, canvas.width / 2, 40); // Position from the top
ctx.strokeText(topText, canvas.width / 2, 40); //Draw the outline
// Draw the bottom text
ctx.fillText(bottomText, canvas.width / 2, canvas.height - 20); // Position from the bottom
ctx.strokeText(bottomText, canvas.width / 2, canvas.height - 20); //Draw the outline
}
// Event listener for the image URL input
imageInput.addEventListener('input', function() {
image.src = this.value; // Set the image source to the entered URL
imageLoaded = false; // Reset the imageLoaded flag
image.onload = function() { // When the image is loaded
imageLoaded = true; // Set the imageLoaded flag
drawMeme(); // Redraw the meme
};
image.onerror = function() {
imageLoaded = false;
alert("Error loading image. Check the URL or ensure CORS is enabled.");
ctx.clearRect(0, 0, canvas.width, canvas.height); //Clear canvas on error
ctx.font = '20px sans-serif';
ctx.fillStyle = 'red';
ctx.textAlign = 'center';
ctx.fillText('Image Load Failed', canvas.width / 2, canvas.height / 2);
}
});
// Event listeners for the text inputs
topTextInput.addEventListener('input', drawMeme);
bottomTextInput.addEventListener('input', drawMeme);
// Event listener for the generate button
generateButton.addEventListener('click', drawMeme);
// Initialize the meme with default values (optional)
image.src = 'https://i.imgflip.com/1bij.jpg'; // A default image
image.onload = function() {
imageLoaded = true;
drawMeme();
};
</script>
</body>
</html>
```
Key improvements and explanations:
* **Clearer Structure:** The HTML is now well-structured with `head`, `body`, and appropriately named IDs. CSS is included for basic styling, making the page look presentable.
* **Image Loading Handling (Crucial):** The code now properly handles image loading. It uses `image.onload` to ensure that the image is fully loaded *before* attempting to draw it on the canvas. This prevents errors and ensures the image appears. It also handles image loading errors gracefully.
* **CORS Handling:** The `image.crossOrigin = "anonymous";` line is *essential* for loading images from different domains (most images on the internet). Without this, the canvas might be tainted, and you won't be able to draw the image data.
* **Error Handling:** Includes an `image.onerror` event handler to catch image loading failures. This is critical for robustness. It displays an alert to the user and clears the canvas, preventing the display of an error message.
* **`imageLoaded` Flag:** The `imageLoaded` boolean variable is used to track whether the image has been loaded successfully. This allows the code to draw a placeholder message ("Loading Image...") if the image is still loading.
* **Text Styling:** Uses `ctx.font`, `ctx.fillStyle`, `ctx.strokeStyle`, and `ctx.textAlign` to set the font, color, outline color, and text alignment for the meme text. Using `Impact` font is a nod to classic meme design. The outline (`strokeText`) makes the text more readable against various backgrounds.
* **Text Case Conversion:** The code now converts the entered text to uppercase using `.toUpperCase()` to match the standard meme format.
* **Clear Canvas:** The `ctx.clearRect()` function is used at the beginning of `drawMeme()` to clear the canvas before drawing. This prevents old meme remnants from showing up.
* **Event Listeners:** Event listeners are attached to the image URL input, top text input, bottom text input, and the generate button. This makes the meme generator interactive. The text input event listeners call `drawMeme()` immediately as the user types, providing a real-time preview.
* **Button Click Trigger:** The `generateButton` now triggers the `drawMeme()` function, which is the desired behavior.
* **Default Image:** Includes a default image URL, so the user sees something on page load.
* **Clear Comments:** The code is heavily commented to explain each step.
* **Concise Code:** The code is written to be efficient and easy to understand.
* **CSS Styling:** Basic CSS is included to improve the presentation of the page.
* **User-Friendly Error Message:** `alert("Error loading image. Check the URL or ensure CORS is enabled.");` tells the user exactly what the issue is likely to be. Displaying an error message directly on the canvas is another possibility.
* **Proper Variable Scope (using `const` and `let`):** Uses `const` for variables that won't be reassigned and `let` for those that will, following modern JavaScript best practices.
How to run this code:
1. **Save:** Save the code as an HTML file (e.g., `meme.html`).
2. **Open in Browser:** Open the HTML file in your web browser (e.g., by double-clicking the file).
3. **Enter Image URL and Text:** Enter the URL of an image you want to use as the base for your meme in the "Image URL" field. Enter the top and bottom text in the corresponding fields.
4. **Generate:** Click the "Generate Meme" button to update the meme on the canvas. The meme updates in real-time as you type.
This improved example is much more robust, handles errors gracefully, and provides a better user experience. It is also structured according to best practices.
👁️ Viewed: 8
Comments