Please bookmark this page to avoid losing your image tool!

Image Safe Dial Filter Effect Tool

(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,
  borderColor = "#B0B0B0",       // Color of the main dial border body
  borderWidth = 20,             // Width of the dial border in pixels (e.g., 20)
  markingsColor = "#000000",     // Color of the tick marks
  showMarkings = 1,             // 0 to hide, 1 to show tick marks
  numTicks = 60,                // Total number of tick positions (e.g., 60)
  majorTickInterval = 5,        // Every Nth tick is a major tick (e.g., 5). Set to 0 to disable distinct major ticks.
  majorTickLengthRatio = 0.7,   // Length of major ticks as a ratio of borderWidth (e.g., 0.7)
  majorTickWidth = 2,           // Width of major ticks in pixels (e.g., 2)
  minorTickLengthRatio = 0.4,   // Length of minor ticks as a ratio of borderWidth (e.g., 0.4)
  minorTickWidth = 1,           // Width of minor ticks in pixels (e.g., 1)
  showCenterKnob = 1,           // 0 to hide, 1 to show center knob
  centerKnobColor = "#707070",   // Color of the center knob
  centerKnobRadiusRatio = 0.1   // Radius of center knob as a ratio of imageRadius (e.g., 0.1 for 10% of image radius)
) {
  const imageDiameter = Math.max(0, Math.min(originalImg.width, originalImg.height));
  const imageRadius = imageDiameter / 2;

  // Sanitize numeric parameters
  const BORDER_WIDTH = Math.max(0, Number(borderWidth));
  const SHOW_MARKINGS = Number(showMarkings) === 1; // Convert to boolean for easier use
  const NUM_TICKS = Math.max(0, Number(numTicks));
  const MAJOR_TICK_INTERVAL = Math.max(0, Number(majorTickInterval));
  const MAJOR_TICK_LENGTH_RATIO = Math.max(0, Math.min(1, Number(majorTickLengthRatio)));
  const MAJOR_TICK_WIDTH = Math.max(0, Number(majorTickWidth));
  const MINOR_TICK_LENGTH_RATIO = Math.max(0, Math.min(1, Number(minorTickLengthRatio)));
  const MINOR_TICK_WIDTH = Math.max(0, Number(minorTickWidth));
  const SHOW_CENTER_KNOB = Number(showCenterKnob) === 1; // Convert to boolean
  const CENTER_KNOB_RADIUS_RATIO = Math.max(0, Number(centerKnobRadiusRatio));
  
  const canvasSize = imageDiameter + 2 * BORDER_WIDTH;
  const canvas = document.createElement('canvas');
  
  // Handle 0-size canvas case early
  if (canvasSize === 0) {
    canvas.width = 0;
    canvas.height = 0;
    return canvas;
  }

  canvas.width = canvasSize;
  canvas.height = canvasSize;
  const ctx = canvas.getContext('2d');

  const cx = canvas.width / 2;
  const cy = canvas.height / 2;

  // 1. Draw the dial border background
  if (BORDER_WIDTH > 0) {
    ctx.fillStyle = borderColor;
    ctx.beginPath();
    ctx.arc(cx, cy, imageRadius + BORDER_WIDTH, 0, Math.PI * 2);
    ctx.fill();
  }

  // 2. Clip and draw the image
  if (imageRadius > 0) {
    ctx.save();
    ctx.beginPath();
    ctx.arc(cx, cy, imageRadius, 0, Math.PI * 2); // Clip to the image area
    ctx.clip();

    // Determine source crop sx, sy, sDim from originalImg to make it square and centered
    const sDim = Math.min(originalImg.width, originalImg.height); // This is imageDiameter
    const sx = (originalImg.width - sDim) / 2;
    const sy = (originalImg.height - sDim) / 2;
    
    ctx.drawImage(originalImg, sx, sy, sDim, sDim, cx - imageRadius, cy - imageRadius, imageDiameter, imageDiameter);
    ctx.restore(); // Remove clipping path for subsequent drawings
  }

  // 3. Draw tick marks
  if (SHOW_MARKINGS && BORDER_WIDTH > 0 && NUM_TICKS > 0) {
    ctx.strokeStyle = markingsColor;
    
    const actualMajorTickLength = BORDER_WIDTH * MAJOR_TICK_LENGTH_RATIO;
    const actualMinorTickLength = BORDER_WIDTH * MINOR_TICK_LENGTH_RATIO;

    for (let i = 0; i < NUM_TICKS; i++) {
      const angle = (i / NUM_TICKS) * 2 * Math.PI - Math.PI / 2; // Start from top (North)

      const isMajorTick = MAJOR_TICK_INTERVAL > 0 && (i % MAJOR_TICK_INTERVAL === 0);
      
      let currentTickLength;
      let currentTickWidth;

      if (isMajorTick) {
        currentTickLength = actualMajorTickLength;
        currentTickWidth = MAJOR_TICK_WIDTH;
      } else {
        currentTickLength = actualMinorTickLength;
        currentTickWidth = MINOR_TICK_WIDTH;
      }

      // Skip drawing if tick has no effective length or width
      if (currentTickLength <= 0 || currentTickWidth <= 0) {
        continue;
      }

      const tickStartX = cx + Math.cos(angle) * imageRadius;
      const tickStartY = cy + Math.sin(angle) * imageRadius;
      const tickEndX = cx + Math.cos(angle) * (imageRadius + currentTickLength);
      const tickEndY = cy + Math.sin(angle) * (imageRadius + currentTickLength);

      ctx.lineWidth = currentTickWidth;
      ctx.beginPath();
      ctx.moveTo(tickStartX, tickStartY);
      ctx.lineTo(tickEndX, tickEndY);
      ctx.stroke();
    }
  }

  // 4. Draw center knob
  if (SHOW_CENTER_KNOB && imageRadius > 0) {
    const actualCenterKnobRadius = imageRadius * CENTER_KNOB_RADIUS_RATIO;
    if (actualCenterKnobRadius > 0) { // Only draw if knob has positive radius
      ctx.fillStyle = centerKnobColor;
      ctx.beginPath();
      ctx.arc(cx, cy, actualCenterKnobRadius, 0, Math.PI * 2);
      ctx.fill();
    }
  }

  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 Safe Dial Filter Effect Tool allows users to apply a customizable dial filter effect to their images. This tool enables users to create dial designs featuring adjustable border colors and widths, tick markings, and a center knob. Use cases for this tool include creating unique graphical representations for devices, designing gauges or dials for applications, and enhancing visual presentations with dial-like effects on images. Users can define specific parameters such as the number of ticks, tick lengths, and center knob appearance to suit their design needs.

Leave a Reply

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