You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
memberName = "Alex Doe",
memberId = `ID-${Math.random().toString(16).slice(2, 10).toUpperCase()}`,
joinDate = (() => {
const d = new Date();
return `${(d.getMonth() + 1).toString().padStart(2, '0')}/${d.getDate().toString().padStart(2, '0')}/${d.getFullYear()}`;
})(),
societyName = "The Ancient Order of Coders",
cardBackgroundColor = "#2c3e50", // Dark Slate Blue
textColor = "#ecf0f1", // Clouds (Light Grayish Blue)
accentColor = "#f1c40f", // Sunflower (Yellow/Gold)
statusActiveColor = "#2ecc71", // Emerald Green
symbolPupilColor = "#111111" // Very Dark Grey/Almost Black
) {
// Helper function to draw the society symbol
function drawSocietySymbol(ctx, x, y, size, triangleColor, irisColor, pupilColor) {
const h = size * (Math.sqrt(3) / 2); // Height of equilateral triangle
// Triangle
ctx.beginPath();
ctx.moveTo(x + size / 2, y); // Top point
ctx.lineTo(x + size, y + h); // Bottom right
ctx.lineTo(x, y + h); // Bottom left
ctx.closePath();
ctx.strokeStyle = triangleColor;
ctx.lineWidth = Math.max(1, Math.floor(size / 18)) + 1; // Proportional line width
ctx.stroke();
// Iris (circle)
const eyeCenterX = x + size / 2;
const eyeCenterY = y + h * 0.57; // Adjusted for visual centering within triangle
const irisRadius = size / 3.8;
ctx.beginPath();
ctx.arc(eyeCenterX, eyeCenterY, irisRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = irisColor;
ctx.fill();
// Pupil (smaller circle)
const pupilRadius = irisRadius / 2.2;
ctx.beginPath();
ctx.arc(eyeCenterX, eyeCenterY, pupilRadius, 0, 2 * Math.PI, false);
ctx.fillStyle = pupilColor;
ctx.fill();
}
const cardWidth = 600;
const cardHeight = 375;
const canvas = document.createElement('canvas');
canvas.width = cardWidth;
canvas.height = cardHeight;
const ctx = canvas.getContext('2d');
// 1. Draw Background
ctx.fillStyle = cardBackgroundColor;
ctx.fillRect(0, 0, cardWidth, cardHeight);
// 2. Draw Top Banner with Society Name
const bannerHeight = 60;
ctx.fillStyle = accentColor;
ctx.fillRect(0, 0, cardWidth, bannerHeight);
// Calculate dynamic font size for banner title
const bannerFontSize = Math.floor(bannerHeight * 0.45);
ctx.font = `bold ${bannerFontSize}px 'Georgia', serif`;
ctx.fillStyle = cardBackgroundColor; // Text color on banner (contrast)
ctx.textAlign = "center";
// Adjust vertical position for better centering of text in banner
const textMetrics = ctx.measureText(societyName); // Not available in all environments for height, but good for width
// A common heuristic for y-position in canvas text:
ctx.fillText(societyName, cardWidth / 2, bannerHeight / 2 + bannerFontSize / 3.5);
// 3. Draw Profile Picture
const picMargin = 25; // Margin around the picture container
const picContainerX = picMargin;
const picContainerY = bannerHeight + picMargin;
const picContainerWidth = 130;
const picContainerHeight = 130;
// Calculate dimensions to fit image within container while maintaining aspect ratio
let newImgWidth, newImgHeight, imgDrawX, imgDrawY;
// Ensure originalImg has dimensions, otherwise gracefully handle (or draw placeholder)
const imgNaturalWidth = originalImg.naturalWidth || picContainerWidth; // Fallback if not loaded
const imgNaturalHeight = originalImg.naturalHeight || picContainerHeight; // Fallback if not loaded
const imgAspectRatio = imgNaturalWidth / imgNaturalHeight;
const containerAspectRatio = picContainerWidth / picContainerHeight;
if (imgAspectRatio > containerAspectRatio) { // Image is wider than container aspect ratio
newImgWidth = picContainerWidth;
newImgHeight = newImgWidth / imgAspectRatio;
} else { // Image is taller or same aspect ratio as container
newImgHeight = picContainerHeight;
newImgWidth = newImgHeight * imgAspectRatio;
}
imgDrawX = picContainerX + (picContainerWidth - newImgWidth) / 2; // Center horizontally
imgDrawY = picContainerY + (picContainerHeight - newImgHeight) / 2; // Center vertically
try {
ctx.drawImage(originalImg, imgDrawX, imgDrawY, newImgWidth, newImgHeight);
} catch (e) {
console.error("Error drawing image:", e);
// Optionally draw a placeholder if image fails
ctx.fillStyle = "#555";
ctx.fillRect(picContainerX, picContainerY, picContainerWidth, picContainerHeight);
ctx.fillStyle = textColor;
ctx.textAlign = "center";
ctx.fillText("No Image", picContainerX + picContainerWidth/2, picContainerY + picContainerHeight/2);
}
// Border for pic container
ctx.strokeStyle = accentColor;
ctx.lineWidth = 3;
ctx.strokeRect(picContainerX, picContainerY, picContainerWidth, picContainerHeight);
// 4. Draw Member Details
const detailsStartX = picContainerX + picContainerWidth + 25; // X start for details text block
let currentTextY = picContainerY + 5; // Initial Y for text block, align near top of picture
ctx.textAlign = "left"; // Reset text align
// "MEMBERSHIP CARD" title under the banner, above details
ctx.font = "italic 20px 'Georgia', serif";
ctx.fillStyle = textColor;
ctx.fillText("MEMBERSHIP CARD", detailsStartX, currentTextY);
currentTextY += 30; // Space after title
// Member info properties
const labelFont = "15px 'Arial', sans-serif";
const valueFont = "bold 15px 'Arial', sans-serif";
const labelValueHorizontalOffset = 110; // X-offset from label start to value start
const lineSpacing = 26; // Vertical space between lines of details
// Name
ctx.font = labelFont;
ctx.fillStyle = textColor; // Ensure text color is set for labels
ctx.fillText("Name:", detailsStartX, currentTextY);
ctx.font = valueFont;
ctx.fillText(memberName, detailsStartX + labelValueHorizontalOffset, currentTextY);
currentTextY += lineSpacing;
// ID
ctx.font = labelFont;
ctx.fillText("ID:", detailsStartX, currentTextY);
ctx.font = valueFont;
ctx.fillText(memberId, detailsStartX + labelValueHorizontalOffset, currentTextY);
currentTextY += lineSpacing;
// Join Date
ctx.font = labelFont;
ctx.fillText("Member Since:", detailsStartX, currentTextY);
ctx.font = valueFont;
ctx.fillText(joinDate, detailsStartX + labelValueHorizontalOffset, currentTextY);
currentTextY += lineSpacing;
// Status
ctx.font = labelFont;
ctx.fillText("Status:", detailsStartX, currentTextY);
ctx.font = valueFont;
ctx.fillStyle = statusActiveColor; // Special color for status value
ctx.fillText("ACTIVE", detailsStartX + labelValueHorizontalOffset, currentTextY);
// Reset fillStyle for other text if any more details were to be added
ctx.fillStyle = textColor;
// 5. Draw Society Symbol (Logo)
const symbolSize = 55; // Base size for the symbol (e.g., width of the triangle)
const symbolMarginFromEdge = 0.05 * cardWidth; // Margin from card edges
const symbolX = cardWidth - symbolSize - symbolMarginFromEdge;
// Calculate symbol's drawn height for precise vertical positioning from bottom
const symbolEffectiveHeight = symbolSize * (Math.sqrt(3) / 2); // Height of equilateral triangle part
const symbolY = cardHeight - symbolEffectiveHeight - (symbolMarginFromEdge * 0.8); // Position from bottom
drawSocietySymbol(ctx, symbolX, symbolY, symbolSize, accentColor, accentColor, symbolPupilColor);
return canvas;
}
Apply Changes