You can edit the below JavaScript code to customize the image tool.
/**
* Creates an image with a speech bubble and an optional audio player.
* The function draws the original image on a canvas, adds a speech bubble with text,
* and then places the canvas and an audio player inside a container DIV.
*
* @param {Image} originalImg The original javascript Image object.
* @param {string} [text='Hello, world!'] The text to display in the speech bubble.
* @param {string} [textColor='#000000'] The color of the text (e.g., '#RRGGBB').
* @param {number} [fontSize=20] The font size of the text in pixels.
* @param {string} [bubbleColor='#FFFFFF'] The fill color of the speech bubble.
* @param {string} [borderColor='#000000'] The border color of the speech bubble.
* @param {string} [bubblePosition='bottomRight'] The position of the speech bubble. Accepts 'topLeft', 'topRight', 'bottomLeft', 'bottomRight'.
* @param {string} [audioSrc=''] The URL or Base64 data URI for the audio file. If empty, no audio player is added.
* @param {number} [audioControls=1] Show audio controls. 1 for true, 0 for false.
* @returns {HTMLDivElement} A DIV element containing the canvas with the speech bubble and an audio player.
*/
function processImage(originalImg, text = 'Hello, world!', textColor = '#000000', fontSize = 20, bubbleColor = '#FFFFFF', borderColor = '#000000', bubblePosition = 'bottomRight', audioSrc = '', audioControls = 1) {
// 1. Create a container element to hold both canvas and audio
const container = document.createElement('div');
container.style.display = 'inline-block';
container.style.width = `${originalImg.naturalWidth}px`;
// 2. Create a canvas and context
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 3. Set canvas dimensions and draw the original image
canvas.width = originalImg.naturalWidth;
canvas.height = originalImg.naturalHeight;
ctx.drawImage(originalImg, 0, 0);
// --- Prepare for drawing text and bubble ---
// Ensure fontSize is a number for calculations
const numericFontSize = parseInt(fontSize, 10) || 20;
const font = `${numericFontSize}px Arial`;
ctx.font = font;
ctx.textBaseline = 'top';
// Define bubble geometry based on image size
const padding = 20; // Padding from image edge
const bubbleWidth = canvas.width * 0.45;
const cornerRadius = 20;
const textPadding = 15; // Padding inside the bubble
// 4. Wrap text to fit inside the bubble
const maxWidth = bubbleWidth - 2 * textPadding;
const words = text.split(' ');
let lines = [];
let currentLine = words[0] || '';
for (let i = 1; i < words.length; i++) {
const word = words[i];
const width = ctx.measureText(currentLine + " " + word).width;
if (width < maxWidth) {
currentLine += " " + word;
} else {
lines.push(currentLine);
currentLine = word;
}
}
lines.push(currentLine);
// 5. Calculate bubble height dynamically based on text content
const lineHeight = numericFontSize * 1.2;
const requiredTextHeight = lines.length * lineHeight;
// Ensure bubble is tall enough for text and corner radius
const bubbleHeight = Math.max(requiredTextHeight + 2 * textPadding, 2 * cornerRadius);
// 6. Determine bubble's top-left (x, y) coordinates based on position
let bubbleX, bubbleY;
switch (bubblePosition) {
case 'topLeft':
bubbleX = padding;
bubbleY = padding + 20; // Add extra padding for tail
break;
case 'topRight':
bubbleX = canvas.width - bubbleWidth - padding;
bubbleY = padding + 20; // Add extra padding for tail
break;
case 'bottomLeft':
bubbleX = padding;
bubbleY = canvas.height - bubbleHeight - padding - 20;
break;
case 'bottomRight':
default:
bubbleX = canvas.width - bubbleWidth - padding;
bubbleY = canvas.height - bubbleHeight - padding - 20;
break;
}
// --- Helper function to draw the bubble with a tail ---
function drawSpeechBubble(ctx, x, y, w, h, r, pos) {
const tailHeight = 20;
const tailWidth = 20;
ctx.beginPath();
ctx.fillStyle = bubbleColor;
ctx.strokeStyle = borderColor;
ctx.lineWidth = 2;
// Path drawing logic
// Top edge
ctx.moveTo(x + r, y);
if (pos === 'topLeft') {
ctx.lineTo(x + w * 0.3, y);
ctx.lineTo(x + w * 0.3 + tailWidth / 2, y - tailHeight);
ctx.lineTo(x + w * 0.3 + tailWidth, y);
} else if (pos === 'topRight') {
ctx.lineTo(x + w - (w * 0.3) - tailWidth, y);
ctx.lineTo(x + w - (w * 0.3) - tailWidth / 2, y - tailHeight);
ctx.lineTo(x + w - (w * 0.3), y);
}
ctx.lineTo(x + w - r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
// Right edge
ctx.lineTo(x + w, y + h - r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
// Bottom edge
if (pos === 'bottomLeft') {
ctx.lineTo(x + w * 0.3 + tailWidth, y + h);
ctx.lineTo(x + w * 0.3 + tailWidth / 2, y + h + tailHeight);
ctx.lineTo(x + w * 0.3, y + h);
} else if (pos === 'bottomRight') {
ctx.lineTo(x + w - (w * 0.3), y + h);
ctx.lineTo(x + w - (w * 0.3) - tailWidth / 2, y + h + tailHeight);
ctx.lineTo(x + w - (w * 0.3) - tailWidth, y + h);
}
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
// Left edge
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
ctx.fill();
ctx.stroke();
}
// 7. Draw the bubble on the canvas
drawSpeechBubble(ctx, bubbleX, bubbleY, bubbleWidth, bubbleHeight, cornerRadius, bubblePosition);
// 8. Draw the wrapped text inside the bubble
ctx.fillStyle = textColor;
lines.forEach((line, index) => {
// Center text horizontally
const textWidth = ctx.measureText(line).width;
const textX = bubbleX + (bubbleWidth - textWidth) / 2;
const textY = bubbleY + textPadding + (index * lineHeight);
ctx.fillText(line, textX, textY);
});
// 9. Append canvas to the container
container.appendChild(canvas);
// 10. Create and append audio player if a source is provided
if (audioSrc && audioSrc.trim() !== '') {
const audio = document.createElement('audio');
audio.src = audioSrc;
if (audioControls === 1) {
audio.controls = true;
}
audio.style.width = '100%';
audio.style.marginTop = '8px';
container.appendChild(audio);
}
// 11. Return the final container element
return container;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Speech and Voice Overlay Tool allows users to create an image that includes a speech bubble displaying custom text and an optional audio player for sound effects or voice narration. Ideal for educators, marketers, and social media users, this tool can be used to enhance images by providing context or commentary, making it perfect for creating engaging visual content such as educational resources, promotional graphics, or entertaining memes with voice overlays.