You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Generates an image of a shoe rack based on specified parameters.
* The originalImg parameter is ignored as this function generates a new image.
*
* @param {Image} originalImg - An unused Image object, included for consistency.
* @param {number} width - The width of the canvas.
* @param {number} height - The height of the canvas.
* @param {number} numLayers - The number of layers or shelves in the shoe rack.
* @param {string} pipeColor - The color of the pipes (e.g., '#FFFFFF').
* @param {string} connectorColor - The color of the connectors (e.g., '#000000').
* @returns {HTMLCanvasElement} A canvas element with the shoe rack drawing.
*/
async function processImage(originalImg, width = 500, height = 450, numLayers = 3, pipeColor = '#FFFFFF', connectorColor = '#000000') {
// 1. Canvas Setup
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Set a background color for better visibility of the shoe rack, especially if pipes are white.
ctx.fillStyle = '#f0f0f0';
ctx.fillRect(0, 0, width, height);
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
// 2. Geometry Parameters
const paddingX = width * 0.15;
const paddingY = height * 0.12;
const rackW = width - 2 * paddingX;
const rackH = height - 2 * paddingY;
const depth = rackW * 0.5;
const layerH = rackH / numLayers;
const pipeThickness = Math.max(4, Math.min(rackW, rackH) / 20);
const connectorRadius = pipeThickness * 0.9;
const numSlats = 4; // Number of slats per shelf
// Perspective offset for the 3D effect
const x0 = paddingX;
const y0 = height - paddingY;
const dx = depth * 0.5;
const dy = -depth * 0.5;
// 3. Data Arrays for Drawing Order (simulates z-index)
const connectors_back = [];
const connectors_front = [];
const pipes_back = [];
const pipes_side = [];
const pipes_front = [];
// 4. Generate Geometry
// 4.1. Vertical Posts
pipes_front.push({ p1: [x0, y0], p2: [x0, y0 - rackH] });
pipes_front.push({ p1: [x0 + rackW, y0], p2: [x0 + rackW, y0 - rackH] });
pipes_back.push({ p1: [x0 + dx, y0 + dy], p2: [x0 + dx, y0 - rackH + dy] });
pipes_back.push({ p1: [x0 + rackW + dx, y0 + dy], p2: [x0 + rackW + dx, y0 - rackH + dy] });
// 4.2. Horizontal Shelf Frames and Slats
for (let i = 0; i <= numLayers; i++) {
const currentY = y0 - i * layerH;
const fl = [x0, currentY]; // front-left point
const fr = [x0 + rackW, currentY]; // front-right
const bl = [x0 + dx, currentY + dy]; // back-left
const br = [x0 + rackW + dx, currentY + dy]; // back-right
connectors_front.push(fl, fr);
connectors_back.push(bl, br);
// Frame pipes
pipes_front.push({ p1: fl, p2: fr });
pipes_back.push({ p1: bl, p2: br });
pipes_side.push({ p1: fl, p2: bl });
pipes_side.push({ p1: fr, p2: br });
// Add slats for the shelf surface (for all levels above the ground)
if (i > 0) {
for (let j = 1; j <= numSlats; j++) {
const ratio = j / (numSlats + 1);
// Interpolate along the side pipes to find the slat endpoints
const p_left = [
fl[0] * (1 - ratio) + bl[0] * ratio,
fl[1] * (1 - ratio) + bl[1] * ratio
];
const p_right = [
fr[0] * (1 - ratio) + br[0] * ratio,
fr[1] * (1 - ratio) + br[1] * ratio
];
pipes_side.push({ p1: p_left, p2: p_right });
}
}
}
// 5. Drawing Phase
const drawPipe = (p1, p2) => {
ctx.beginPath();
ctx.moveTo(p1[0], p1[1]);
ctx.lineTo(p2[0], p2[1]);
// Draw a subtle outline for light-colored pipes to make them stand out
const isWhite = pipeColor.toLowerCase() === '#ffffff' || pipeColor.toLowerCase() === 'white';
if (isWhite) {
ctx.strokeStyle = '#b0b0b0';
ctx.lineWidth = pipeThickness + 1.5;
ctx.stroke();
}
// Draw the main pipe
ctx.strokeStyle = pipeColor;
ctx.lineWidth = pipeThickness;
ctx.stroke();
};
const drawConnector = (p) => {
ctx.beginPath();
ctx.arc(p[0], p[1], connectorRadius, 0, 2 * Math.PI);
ctx.fillStyle = connectorColor;
ctx.fill();
// Optional: add a subtle stroke to connectors for definition
ctx.strokeStyle = 'rgba(255,255,255,0.2)';
ctx.lineWidth = 1;
ctx.stroke();
};
// Draw elements in order from back to front
pipes_back.forEach(pipe => drawPipe(pipe.p1, pipe.p2));
connectors_back.forEach(p => drawConnector(p));
pipes_side.forEach(pipe => drawPipe(pipe.p1, pipe.p2));
pipes_front.forEach(pipe => drawPipe(pipe.p1, pipe.p2));
connectors_front.forEach(p => drawConnector(p));
return canvas;
}
Apply Changes