Please bookmark this page to avoid losing your image tool!

Image Radar Scan Filter Effect 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,
    scanAngleDegrees = 45,
    scanColor = "rgba(100, 255, 100, 0.7)", // Color of the scanning beam. Assumed to be rgba/hsla for transparency manipulation.
    scanArcWidthDegrees = 60,       // Width of the beam in degrees
    overlayColor = "rgba(0, 30, 0, 0.4)",  // Overall green tint
    grayscaleImage = 1,             // 1 to apply grayscale to original image, 0 to keep colors
    showGrid = 1,                   // 1 to show grid lines, 0 to hide
    gridColor = "rgba(50, 150, 50, 0.6)", // Color of grid lines
    gridCircles = 5,                // Number of concentric circles in the grid
    gridLines = 8,                  // Number of radial lines in the grid
    centerCrosshair = 1,            // 1 to show center crosshair, 0 to hide
    crosshairColor = "rgba(50, 150, 50, 0.8)" // Color of center crosshair
) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    canvas.width = originalImg.naturalWidth || originalImg.width || 0;
    canvas.height = originalImg.naturalHeight || originalImg.height || 0;

    if (canvas.width === 0 || canvas.height === 0) {
        // Return empty canvas if image has no dimensions, or dimensions couldn't be determined
        return canvas;
    }

    const cx = canvas.width / 2;
    const cy = canvas.height / 2;
    const radius = Math.min(cx, cy);

    // --- Start drawing ---
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // 1. Outer Circular Mask
    ctx.save(); // Save context state before clipping
    ctx.beginPath();
    ctx.arc(cx, cy, radius, 0, 2 * Math.PI);
    ctx.clip();

    // 2. Draw Original Image (optionally grayscaled)
    if (grayscaleImage === 1) {
        ctx.filter = 'grayscale(100%)';
    }
    ctx.drawImage(originalImg, 0, 0, canvas.width, canvas.height);
    if (grayscaleImage === 1) {
        ctx.filter = 'none'; // Reset filter
    }

    // 3. Apply Overlay Color to the entire clipped circular area
    if (overlayColor && overlayColor !== "transparent" && !overlayColor.endsWith(", 0)") && !overlayColor.endsWith(",0)")) { // Check for actual color vs fully transparent
        ctx.fillStyle = overlayColor;
        ctx.fillRect(0, 0, canvas.width, canvas.height); // Will be clipped to circle
    }


    // 4. Draw Grid
    if (showGrid === 1 && (gridCircles > 0 || gridLines > 0)) {
        ctx.strokeStyle = gridColor;
        ctx.lineWidth = 1; // Consider making this a parameter or adaptive based on radius

        // Concentric circles
        if (gridCircles > 0) {
            for (let i = 0; i < gridCircles; i++) {
                ctx.beginPath();
                const circleRadius = (radius / gridCircles) * (i + 1);
                ctx.arc(cx, cy, circleRadius, 0, 2 * Math.PI);
                ctx.stroke();
            }
        }

        // Radial lines
        if (gridLines > 0) {
            for (let i = 0; i < gridLines; i++) {
                // Ensure lines don't converge messily at the very center if crosshair is also there
                const lineStartRadius = (centerCrosshair === 1 && radius * 0.05 > 5) ? Math.min(radius * 0.05, 10) : 0;
                const angle = (2 * Math.PI / gridLines) * i;
                ctx.beginPath();
                ctx.moveTo(cx + lineStartRadius * Math.cos(angle), cy + lineStartRadius * Math.sin(angle));
                ctx.lineTo(cx + radius * Math.cos(angle), cy + radius * Math.sin(angle));
                ctx.stroke();
            }
        }
    }

    // 5. Draw Scan Beam
    // Clamp scanArcWidthDegrees to be < 360 for conic gradient color stop logic
    const effectiveScanArcWidthDegrees = Math.max(0, Math.min(scanArcWidthDegrees, 359.999));
    
    if (effectiveScanArcWidthDegrees > 0) { // Only draw beam if it has a width
        const scanAngleRad = (scanAngleDegrees * Math.PI / 180);

        // Prepare transparent version of scanColor. Assumes scanColor is rgba or hsla.
        let transparentScanColor = "rgba(0,0,0,0)"; // Fallback
        const lastCommaIndex = scanColor.lastIndexOf(',');
        const colorPrefix = scanColor.substring(0, lastCommaIndex + 1).toLowerCase();

        if (lastCommaIndex !== -1 && (colorPrefix.startsWith("rgba(") || colorPrefix.startsWith("hsla("))) {
            transparentScanColor = scanColor.substring(0, lastCommaIndex + 1) + "0)";
        } else {
            // For non-rgba/hsla explicitly, this is a simple guess.
            // A more robust solution would parse various color formats (hex, rgb, names).
            // For now, warn and use a default fully transparent black.
            if (typeof console !== 'undefined' && console.warn) {
                 console.warn("Radar scan beam's fade-to-transparent effect might not be ideal if scanColor is not in rgba/hsla format that includes an alpha value. Using default transparent for fade effect.");
            }
        }

        if (typeof ctx.createConicGradient === "function") {
            const arcFraction = (effectiveScanArcWidthDegrees / 2) / 360; // Fraction of full circle for half arc
            const beamGradient = ctx.createConicGradient(scanAngleRad, cx, cy);
            
            beamGradient.addColorStop(0, scanColor); // Peak color at the center of the beam
            beamGradient.addColorStop(arcFraction, transparentScanColor);
            // The gradient wraps, so a stop at 1-arcFraction makes the other side of the beam fade
            beamGradient.addColorStop(1 - arcFraction, transparentScanColor); 
            
            ctx.fillStyle = beamGradient;
            ctx.fillRect(0, 0, canvas.width, canvas.height); // Fill the clipped circle
        } else { 
            // Fallback for browsers not supporting conic gradient: Draw a solid arc
            const beamWidthRad = effectiveScanArcWidthDegrees * Math.PI / 180;
            const beamStartAngleRad = scanAngleRad - beamWidthRad / 2;
            const beamEndAngleRad = scanAngleRad + beamWidthRad / 2;

            ctx.fillStyle = scanColor;
            ctx.beginPath();
            ctx.moveTo(cx, cy);
            ctx.arc(cx, cy, radius, beamStartAngleRad, beamEndAngleRad);
            ctx.closePath();
            ctx.fill();
            if (typeof console !== 'undefined' && console.warn) {
                console.warn("Radar scan beam uses a solid color because createConicGradient is not supported in this browser environment.");
            }
        }
    }

    // 6. Draw Center Crosshair
    if (centerCrosshair === 1) {
        ctx.strokeStyle = crosshairColor;
        ctx.lineWidth = 1; 
        const crosshairSize = Math.min(radius * 0.05, 10); // Adaptive size, capped at 10px
        ctx.beginPath();
        ctx.moveTo(cx - crosshairSize, cy);
        ctx.lineTo(cx + crosshairSize, cy); // Horizontal line
        ctx.moveTo(cx, cy - crosshairSize);
        ctx.lineTo(cx, cy + crosshairSize); // Vertical line
        ctx.stroke();
    }

    // 7. Restore from Outer Circular Mask clip
    ctx.restore(); // Restore context state from before clipping

    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 Radar Scan Filter Effect Creator is a versatile online tool that allows users to apply a radar scan filter effect to their images. Utilizing customizable parameters, users can generate an aesthetically pleasing radar-like appearance on their images, with options to adjust the scan angle, color, arc width, overlay color, and more. This tool is suitable for creating unique visuals for presentations, enhancing graphics for game development, or generating eye-catching social media content. Additionally, users can choose to display a grid and center crosshair, providing a detailed reference for positioning and layout, making it a valuable resource for designers and artists.

Leave a Reply

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