You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
text = "MOIRÉ",
fontSize = 200,
fontFamily = "Impact, Arial, sans-serif",
textColor = "#000000",
lineColor = "#ffffff",
lineThickness = 2,
lineSpacing1 = 6,
lineSpacing2 = 6.2,
angle1 = -45,
angle2 = -40,
posX = 0.5,
posY = 0.5,
addShadow = 1
) {
// Parse numeric constraints to ensure proper drawing
fontSize = Number(fontSize) || 200;
lineThickness = Math.max(0.1, Number(lineThickness) || 2);
lineSpacing1 = Math.max(lineThickness + 0.1, Number(lineSpacing1) || 6);
lineSpacing2 = Math.max(lineThickness + 0.1, Number(lineSpacing2) || 6.2);
angle1 = Number(angle1) !== NaN ? Number(angle1) : -45;
angle2 = Number(angle2) !== NaN ? Number(angle2) : -40;
posX = !isNaN(Number(posX)) ? Number(posX) : 0.5;
posY = !isNaN(Number(posY)) ? Number(posY) : 0.5;
addShadow = !isNaN(Number(addShadow)) ? Number(addShadow) : 1;
// Set up main output canvas
const canvas = document.createElement('canvas');
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalHeight || originalImg.height;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Draw the background original image
ctx.drawImage(originalImg, 0, 0, width, height);
// Set up an off-screen canvas to generate the Moiré text effect
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
const tCtx = tempCanvas.getContext('2d');
// Draw solid text mask
tCtx.font = `bold ${fontSize}px ${fontFamily}`;
tCtx.textBaseline = "middle";
tCtx.textAlign = "center";
tCtx.fillStyle = textColor;
// Support multi-line text (if separated by \n)
const lines = text.split('\\n').map(line => line.split('\n')).flat();
const lineHeight = fontSize * 1.1;
const startY = height * posY - ((lines.length - 1) * lineHeight) / 2;
lines.forEach((line, index) => {
tCtx.fillText(line, width * posX, startY + (index * lineHeight));
});
// Change composite operation to source-atop.
// Anything drawn now only appears INSIDE the text mask drawn above.
tCtx.globalCompositeOperation = "source-atop";
// Helper function to draw full-canvas parallel lines
function drawStripes(context, w, h, thickness, spacing, angle, color) {
context.save();
// Move to center to naturally rotate around the middle of the canvas
context.translate(w / 2, h / 2);
context.rotate(angle * Math.PI / 180);
// Calculate the maximum diagonal to ensure stripes cover the edges when rotated
const diag = Math.sqrt(w * w + h * h);
context.fillStyle = color;
// Draw stripes
for (let y = -diag; y < diag; y += spacing) {
context.fillRect(-diag, y, diag * 2, thickness);
}
context.restore();
}
// Drawing two overlaid stripe patterns inside the text.
// The slight difference in angles and/or spacing creates the optical Moiré interference pattern.
drawStripes(tCtx, width, height, lineThickness, lineSpacing1, angle1, lineColor);
drawStripes(tCtx, width, height, lineThickness, lineSpacing2, angle2, lineColor);
// Optional: Draw drop shadow to make the text pop against the source image
if (addShadow === 1) {
ctx.shadowColor = "rgba(0, 0, 0, 0.75)";
ctx.shadowBlur = Math.max(10, fontSize / 10);
ctx.shadowOffsetX = Math.max(4, fontSize / 30);
ctx.shadowOffsetY = Math.max(4, fontSize / 30);
}
// Merge the Moiré text onto the original image
ctx.drawImage(tempCanvas, 0, 0, width, height);
return canvas;
}
Apply Changes