Please bookmark this page to avoid losing your image tool!

Breaking News Banner Template 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.
function processImage(
    originalImg, 
    headline = "BREAKING NEWS", 
    subhead = "MAJOR EVENT UNFOLDS AS WORLD WATCHES LIVE", 
    ticker = "UPDATE: NEW DETAILS EMERGING... TRUTH REVEALED...", 
    liveText = "LIVE", 
    themeColor = "#cc0000", 
    textColor = "#000000"
) {
    const canvas = document.createElement('canvas');
    canvas.width = originalImg.width;
    canvas.height = originalImg.height;
    const ctx = canvas.getContext('2d');

    // Draw original image as background
    ctx.drawImage(originalImg, 0, 0);

    const W = canvas.width;
    const H = canvas.height;

    // Dimensions
    const tickerH = Math.max(H * 0.07, 24);
    const mainH = Math.max(H * 0.12, 40);
    const tickerY = H - tickerH;
    const mainY = tickerY - mainH;
    
    // Slant calculations (slants forwards / )
    const splitX_top = W * 0.30;
    const splitX_bot = W * 0.33;

    const redBox = [
        {x: 0, y: mainY},
        {x: splitX_top, y: mainY},
        {x: splitX_bot, y: mainY + mainH},
        {x: 0, y: mainY + mainH}
    ];

    const whiteBox = [
        {x: splitX_top, y: mainY},
        {x: W, y: mainY},
        {x: W, y: mainY + mainH},
        {x: splitX_bot, y: mainY + mainH}
    ];

    // Helper to draw polygons
    function drawPoly(points, fillStyle) {
        ctx.fillStyle = fillStyle;
        ctx.beginPath();
        ctx.moveTo(points[0].x, points[0].y);
        for(let i = 1; i < points.length; i++) {
            ctx.lineTo(points[i].x, points[i].y);
        }
        ctx.closePath();
        ctx.fill();
    }

    // Main lighting gradient for TV glossy effect
    const glossyOverlay = ctx.createLinearGradient(0, mainY, 0, mainY + mainH);
    glossyOverlay.addColorStop(0, 'rgba(255, 255, 255, 0.4)');
    glossyOverlay.addColorStop(0.4, 'rgba(255, 255, 255, 0.05)');
    glossyOverlay.addColorStop(0.5, 'rgba(0, 0, 0, 0.05)');
    glossyOverlay.addColorStop(1, 'rgba(0, 0, 0, 0.3)');

    // 1. Draw Main Banner (Headline & Subhead blocks)
    // Left Block (Red/Theme)
    drawPoly(redBox, themeColor);
    drawPoly(redBox, glossyOverlay);

    // Right Block (White/Solid)
    drawPoly(whiteBox, '#f5f5f5');
    drawPoly(whiteBox, glossyOverlay);

    // Top Accent Border Line over the white box
    ctx.fillStyle = themeColor;
    ctx.fillRect(splitX_top, mainY - H * 0.005, W - splitX_top, H * 0.005);

    // 2. Draw Bottom Ticker
    ctx.fillStyle = '#111111';
    ctx.fillRect(0, tickerY, W, tickerH);

    // Time Box (Bottom Right)
    const timeBoxW = W * 0.12;
    const timeX = W - timeBoxW;
    ctx.fillStyle = themeColor;
    ctx.fillRect(timeX, tickerY, timeBoxW, tickerH);

    // Helper for shrink-to-fit text
    function writeShrinkText(text, x, y, width, height, color, align = 'left', maxFontSize = 100) {
        let fontSize = maxFontSize;
        ctx.fillStyle = color;
        ctx.textAlign = align;
        ctx.textBaseline = 'middle';
        
        while (fontSize > 4) {
            ctx.font = `900 ${fontSize}px Impact, "Arial Black", Arial, sans-serif`;
            const metrics = ctx.measureText(text);
            if (metrics.width <= width && fontSize <= height) break;
            fontSize--;
        }

        let finalX = x;
        if (align === 'center') finalX = x + width / 2;
        else if (align === 'right') finalX = x + width;

        // Shadow for bright texts for readability
        if (color === '#ffffff' || color === 'white') {
            ctx.shadowColor = 'rgba(0,0,0,0.6)';
            ctx.shadowBlur = 4;
            ctx.shadowOffsetX = 2;
            ctx.shadowOffsetY = 2;
        }

        ctx.fillText(text, finalX, y + height / 2 + (fontSize * 0.05));
        ctx.shadowColor = 'transparent'; // Reset
    }

    // Draw Headline Text (Red Box)
    const redTextMaxWidth = splitX_top * 0.85;
    const redTextX = (splitX_top / 2); // Center of top width
    writeShrinkText(headline, redTextX - (redTextMaxWidth/2), mainY, redTextMaxWidth, mainH * 0.7, '#ffffff', 'center', mainH * 0.65);

    // Draw Subhead Text (White Box)
    const whiteTextStartX = splitX_bot + (W * 0.02);
    const whiteTextMaxWidth = W - whiteTextStartX - (W * 0.02);
    writeShrinkText(subhead, whiteTextStartX, mainY, whiteTextMaxWidth, mainH * 0.7, textColor, 'left', mainH * 0.6);

    // Draw Clock (Time Box)
    const now = new Date();
    const timeStr = now.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' });
    writeShrinkText(timeStr, timeX, tickerY, timeBoxW, tickerH * 0.8, '#ffffff', 'center', tickerH * 0.6);

    // Draw Ticker Text (Using clipping for authentic scroll cut-off)
    const tickerTextW = timeX - (W * 0.02);
    ctx.save();
    ctx.beginPath();
    ctx.rect(W * 0.02, tickerY, tickerTextW, tickerH);
    ctx.clip(); // Ensure long texts don't run into the clock

    ctx.fillStyle = '#ffcc00'; // Classic ticker yellow
    ctx.font = `bold ${tickerH * 0.55}px Arial, sans-serif`;
    ctx.textAlign = 'left';
    ctx.textBaseline = 'middle';
    ctx.fillText(" " + ticker, W * 0.02, tickerY + tickerH / 2 + tickerH * 0.05);
    ctx.restore();

    // 3. Draw LIVE Indicator (Top Left Bug)
    if (liveText && liveText.trim() !== '') {
        const liveH = Math.max(H * 0.045, 25);
        const fontSz = liveH * 0.6;
        ctx.font = `900 ${fontSz}px Arial, sans-serif`;
        const liveTextW = ctx.measureText(liveText).width;
        
        const r = liveH * 0.2; // Blinking circle radius
        const liveW = liveTextW + (r * 2) + (liveH * 0.6) + (liveH * 0.4); 
        const liveX = W * 0.04;
        const liveY = H * 0.04;

        // Banner Base
        ctx.fillStyle = themeColor;
        ctx.fillRect(liveX, liveY, liveW, liveH);
        
        // Gloss
        const liveGloss = ctx.createLinearGradient(0, liveY, 0, liveY + liveH);
        liveGloss.addColorStop(0, 'rgba(255,255,255,0.4)');
        liveGloss.addColorStop(1, 'rgba(0,0,0,0.2)');
        ctx.fillStyle = liveGloss;
        ctx.fillRect(liveX, liveY, liveW, liveH);

        // Recording Dot White Circle
        const cx = liveX + (liveH * 0.5);
        const cy = liveY + (liveH / 2);
        ctx.beginPath();
        ctx.arc(cx, cy, r, 0, Math.PI * 2);
        ctx.fillStyle = '#ffffff';
        ctx.shadowColor = 'rgba(0,0,0,0.5)';
        ctx.shadowBlur = 3;
        ctx.fill();
        ctx.shadowColor = 'transparent';

        // liveText
        const textStartX = cx + r + (liveH * 0.25);
        writeShrinkText(liveText, textStartX, liveY, liveW, liveH * 0.8, '#ffffff', 'left', fontSz);
    }

    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 Breaking News Banner Template Creator allows you to overlay professional, news-style graphics onto any image. This tool enables users to customize headlines, subheadlines, scrolling ticker text, and ‘LIVE’ indicators, while also adjusting theme colors to match a specific aesthetic. It is ideal for content creators, journalists, or social media managers looking to create eye-catching breaking news visuals, dramatic announcements, or broadcast-style graphics for videos and digital posts.

Leave a Reply

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