Please bookmark this page to avoid losing your image tool!

Image Social Media Milestone Certificate Creator

(Free & Supports Bulk Upload)

Drag & drop your images here or

The result will appear here...
You can edit the below JavaScript code to customize the image tool.
async function processImage(
    originalImg,
    milestoneText = "1,000 Followers",
    platformName = "Social Media",
    userName = "Valued User",
    dateText = "", // Default to empty; function logic will set current date
    bgColor = "#F8F0E3", // Parchment-like background
    textColor = "#4A3B31", // Dark brown for text
    accentColor = "#8B4513", // Saddle brown for accents
    titleText = "Certificate of Milestone Achievement",
    awarderName = "The Community",
    fontFamily = "Georgia"
) {
    const canvas = document.createElement('canvas');
    const canvasWidth = 1200;
    const canvasHeight = 900;
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;
    const ctx = canvas.getContext('2d');

    // Attempt to load the specified font family to make it available for rendering.
    // This uses the document.fonts API when available.
    if (document.fonts && typeof document.fonts.load === 'function') {
        try {
            // Load different styles of the font used in the certificate.
            // '1em' is a common size choice for a presence check.
            await Promise.all([
                document.fonts.load(`1em "${fontFamily}"`),
                document.fonts.load(`bold 1em "${fontFamily}"`),
                document.fonts.load(`italic 1em "${fontFamily}"`)
            ]);
        } catch (err) {
            console.warn(`Font "${fontFamily}" might not be available or loadable. Error: ${err}. Canvas will use system fallbacks.`);
            // The browser will use its fallback font (e.g., 'serif' or 'sans-serif' as specified below).
        }
    }
    
    // Helper function to construct a font string with fallbacks.
    // Quotes are used around font family name for robustness (e.g., if it contains spaces).
    function getFont(style, size, FONT_FAMILY_TO_USE = fontFamily) {
        return `${style} ${size}px "${FONT_FAMILY_TO_USE}", serif`; // Fallback to generic serif
    }

    // Helper function to draw text, truncating with an ellipsis if it exceeds maxWidth.
    function fillTextMaxWidth(text, x, y, maxWidth, fontStyle, fontSize, color, textAlign = "center") {
        ctx.font = getFont(fontStyle, fontSize);
        ctx.fillStyle = color;
        ctx.textAlign = textAlign;
        
        let currentText = String(text); // Ensure text is a string.
        let width = ctx.measureText(currentText).width;
        
        // If text fits, draw it directly.
        if (width <= maxWidth) {
            ctx.fillText(currentText, x, y);
            return;
        }
        
        // If text exceeds maxWidth, truncate it and add an ellipsis.
        const ellipsis = "…";
        const ellipsisWidth = ctx.measureText(ellipsis).width;
        // Iterate backwards, reducing text length until it fits with the ellipsis.
        while (width + ellipsisWidth > maxWidth && currentText.length > 0) {
            currentText = currentText.substring(0, currentText.length - 1);
            width = ctx.measureText(currentText).width;
        }
        ctx.fillText(currentText + ellipsis, x, y);
    }
    
    // Helper function to draw a star shape (used for decorative seals).
    function drawStarShape(cx, cy, spikes, outerRadius, innerRadius, fillColor, strokeColor = null, strokeWidth = 0) {
        let rot = Math.PI / 2 * 3; // Start drawing from the top point.
        let x, y;
        const step = Math.PI / spikes; // Angle between points.

        ctx.beginPath();
        ctx.moveTo(cx, cy - outerRadius); // Move to the first outer point.
        for (let i = 0; i < spikes; i++) {
            // Calculate and draw line to the next outer point.
            x = cx + Math.cos(rot) * outerRadius;
            y = cy + Math.sin(rot) * outerRadius;
            ctx.lineTo(x, y);
            rot += step;

            // Calculate and draw line to the next inner point.
            x = cx + Math.cos(rot) * innerRadius;
            y = cy + Math.sin(rot) * innerRadius;
            ctx.lineTo(x, y);
            rot += step;
        }
        ctx.lineTo(cx, cy - outerRadius); // Close the path by connecting to the starting point.
        ctx.closePath();

        ctx.fillStyle = fillColor;
        ctx.fill();

        if (strokeColor && strokeWidth > 0) {
            ctx.strokeStyle = strokeColor;
            ctx.lineWidth = strokeWidth;
            ctx.stroke();
        }
    }

    // --- Start Drawing Certificate ---

    // 1. Background Color
    ctx.fillStyle = bgColor;
    ctx.fillRect(0, 0, canvasWidth, canvasHeight);

    // 2. Borders
    // Outer thick border
    ctx.strokeStyle = accentColor;
    ctx.lineWidth = 15;
    ctx.strokeRect(15, 15, canvasWidth - 30, canvasHeight - 30);
    // Inner thinner border
    ctx.strokeStyle = textColor; // Using main text color for subtlety.
    ctx.lineWidth = 3;
    ctx.strokeRect(40, 40, canvasWidth - 80, canvasHeight - 80);
    
    // Default text alignment for most elements on the certificate.
    ctx.textAlign = "center";

    // Max width for text elements to ensure they stay within the inner border.
    const contentMaxWidth = canvasWidth - 160; // 80px margin on each side from canvas edge.

    // 3. Main Title
    fillTextMaxWidth(titleText, canvasWidth / 2, 120, contentMaxWidth, "bold", 60, accentColor);

    // 4. "Presented to" Label
    fillTextMaxWidth("Proudly Presented To", canvasWidth / 2, 200, contentMaxWidth, "normal", 30, textColor);
    
    // 5. User Name
    fillTextMaxWidth(userName, canvasWidth / 2, 255, contentMaxWidth, "bold", 45, textColor);

    // 6. User Image (originalImg)
    const imgSize = 150;
    const imgX = canvasWidth / 2 - imgSize / 2;
    const imgY = 300; // Positioned below the user name.
    ctx.save(); // Save context state for clipping operation.
    ctx.beginPath();
    ctx.arc(imgX + imgSize / 2, imgY + imgSize / 2, imgSize / 2, 0, Math.PI * 2, true); // Define circular clipping path.
    ctx.closePath();
    ctx.clip(); // Apply clipping.
    try { // Draw the image, with error handling for invalid or unloaded images.
        if (originalImg && originalImg.complete && originalImg.naturalWidth !== 0) {
             ctx.drawImage(originalImg, imgX, imgY, imgSize, imgSize);
        } else {
            throw new Error("Image not loaded, incomplete, or invalid.");
        }
    } catch (e) {
        console.error("Error drawing originalImg:", e);
        // Draw a placeholder if the image fails to load or is invalid.
        ctx.fillStyle = "#DDD"; // Light gray placeholder background.
        ctx.fillRect(imgX, imgY, imgSize, imgSize);
        ctx.fillStyle = "#888"; // Darker gray text for placeholder.
        ctx.font = getFont("normal", 18);
        ctx.textAlign = "center"; // Ensure placeholder text is centered.
        ctx.fillText("No Image", imgX + imgSize / 2, imgY + imgSize / 2 + 8); // Roughly center text.
    }
    ctx.restore(); // Restore context state (remove clipping).
    // Draw a border around the (now circular) image.
    ctx.beginPath();
    ctx.arc(imgX + imgSize / 2, imgY + imgSize / 2, imgSize / 2, 0, Math.PI * 2, true);
    ctx.strokeStyle = accentColor;
    ctx.lineWidth = 4;
    ctx.stroke();

    // 7. "For achieving" Label
    const textBlockYStart = imgY + imgSize + 60; // Y-coordinate for the text block below the image.
    fillTextMaxWidth("For successfully achieving the milestone of", canvasWidth / 2, textBlockYStart, contentMaxWidth, "normal", 30, textColor);

    // 8. Milestone Description
    fillTextMaxWidth(milestoneText, canvasWidth / 2, textBlockYStart + 50, contentMaxWidth, "bold", 40, accentColor);

    // 9. Platform Name
    fillTextMaxWidth(`on ${platformName}`, canvasWidth / 2, textBlockYStart + 95, contentMaxWidth, "italic", 30, textColor);

    // 10. Date of Achievement
    let displayDate = String(dateText).trim(); // Ensure dateText is a string and remove whitespace.
    if (!displayDate) { // If dateText is empty, use the current date.
        const today = new Date();
        try {
            displayDate = today.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });
        } catch (e) { // Fallback for environments where toLocaleDateString with options might fail.
            displayDate = `${today.getDate()}/${today.getMonth() + 1}/${today.getFullYear()}`;
        }
    }
    fillTextMaxWidth("Date: " + displayDate, canvasWidth / 2, textBlockYStart + 160, contentMaxWidth, "normal", 24, textColor);

    // 11. Awarder Name
    const awarderLineY = canvasHeight - 85; // Y-coordinate for the final line of text, near the bottom.
    fillTextMaxWidth("Awarded by: " + awarderName, canvasWidth / 2, awarderLineY, contentMaxWidth, "normal", 24, textColor);

    // 12. Decorative Seals
    const sealRadius = 40;
    const sealY = canvasHeight - 90; // Vertically align seals roughly with the awarder text line.

    // Left Seal
    const sealXLeft = canvasWidth * 0.15; // Position on the lower left.
    ctx.beginPath(); // Background for the seal (acts as an outer border).
    ctx.arc(sealXLeft, sealY, sealRadius + 2, 0, Math.PI * 2);
    ctx.fillStyle = accentColor; 
    ctx.fill();
    ctx.beginPath(); // Main body of the seal.
    ctx.arc(sealXLeft, sealY, sealRadius, 0, Math.PI * 2);
    ctx.fillStyle = "#E1C998"; // Light gold/bronze color.
    ctx.fill();
    drawStarShape(sealXLeft, sealY, 5, sealRadius * 0.65, sealRadius * 0.3, accentColor); // 5-pointed star symbol inside.

    // Right Seal
    const sealXRight = canvasWidth * 0.85; // Position on the lower right.
    // This seal uses a stroke with bgColor to create a "cut-out" or embossed look.
    drawStarShape(sealXRight, sealY, 8, sealRadius, sealRadius * 0.75, accentColor, bgColor, 3); // 8-pointed star seal.

    return canvas;
}

Free Image Tool Creator

Can't find the image tool you're looking for?
Create one based on your own needs now!

Description

The Image Social Media Milestone Certificate Creator is a web tool that allows users to design personalized certificates celebrating achievements on social media platforms. With customizable options including milestone text, user name, platform name, award date, and a choice of colors, users can create visually appealing certificates suitable for commemorating milestones such as reaching follower counts or engagement goals. This tool is ideal for social media influencers, community managers, or anyone looking to recognize and celebrate digital accomplishments creatively.

Leave a Reply

Your email address will not be published. Required fields are marked *

Other Image Tools:

Halloween Death Certificate Template

Image Anatomical Illustration Frame Creator

Image Romance Novel Cover Template Creator

Image Tabloid Headline Template

Image Space Mission Patch Template Creator

Image Cassette Tape Cover Template Creator

Image Passport Page Template Generator

Image Old Map Frame With Compass Rose Decorator

Image Diploma and Degree Certificate Framer

Image Soviet Propaganda Poster Style Generator

Image Yu-Gi-Oh Card Template Creator

Image Ancient Roman Greek Tablet Frame Creator

Image Marriage Certificate Template Creator

Image Video Game Achievement Frame Creator

Image Newspaper Front Page Template Creator

Image Botanical Illustration Frame Creator

Image Vinyl Record Sleeve Template Creator

Vintage Photo Booth Strip Template Generator

Image Cyberpunk Interface Frame Designer

Image Detective Novel Cover Template

Image Achievement Certificate Framer

Image Illuminated Manuscript Frame Generator

Image Art Deco Poster Frame Creator

Image Egyptian Papyrus Scroll Frame Designer

Image Vintage Postage Stamp Frame Creator

Image Magic: The Gathering Card Frame Generator

Image Birth Certificate Template Generator

Image Driver’s License Template Creator

Image Scout Explorer Badge Template Creator

Image Steampunk Document Frame Creator

Image Vintage Scientific Illustration Frame Creator

Image Magazine Cover Template Creator

Image Album Cover Template Creator

Image Medieval Bestiary Page Template

Image Polaroid Instant Photo Frame

Image Pulp Fiction Book Cover Template

See All →