You can edit the below JavaScript code to customize the image tool.
Apply Changes
/**
* Creates an interactive image comparison slider element.
*
* @param {HTMLImageElement} originalImg The base image element for the comparison.
* @param {string} secondImgSrc A URL or Data URI for the second image to compare against.
* @param {string} orientation The slider orientation, either 'horizontal' or 'vertical'.
* @param {string} label1 The text label for the base image (left/top side).
* @param {string} label2 The text label for the second image (right/bottom side).
* @param {number} initialPosition The initial position of the slider as a percentage (0-100).
* @returns {Promise<HTMLDivElement>} A promise that resolves to the container DIV element for the comparison tool.
*/
async function processImage(originalImg, secondImgSrc = '', orientation = 'horizontal', label1 = 'Channel', label2 = 'YouTube', initialPosition = 50) {
// --- 1. Validate inputs and prepare images ---
if (!originalImg || !(originalImg instanceof HTMLImageElement) || !originalImg.width) {
const errorDiv = document.createElement('div');
errorDiv.textContent = 'Error: The first parameter must be a loaded HTMLImageElement.';
return errorDiv;
}
// If no second image is provided, create a placeholder.
if (!secondImgSrc) {
const canvas = document.createElement('canvas');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#888';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'white';
ctx.font = `bold ${Math.min(24, originalImg.width / 15)}px sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Second Image', canvas.width / 2, canvas.height / 2);
secondImgSrc = canvas.toDataURL();
}
// Load the second image asynchronously.
const secondImg = await new Promise((resolve) => {
const img = new Image();
img.crossOrigin = "Anonymous";
img.onload = () => resolve(img);
img.onerror = () => {
// Create a fallback error image if loading fails.
const canvas = document.createElement('canvas');
canvas.width = originalImg.width;
canvas.height = originalImg.height;
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#ffdddd';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'red';
ctx.font = `bold ${Math.min(24, originalImg.width / 15)}px sans-serif`;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText('Error loading image', canvas.width / 2, canvas.height / 2);
const errorImg = new Image();
errorImg.src = canvas.toDataURL();
errorImg.onload = () => resolve(errorImg);
};
img.src = secondImgSrc;
});
const width = originalImg.width;
const height = originalImg.height;
// --- 2. Create the HTML structure ---
const container = document.createElement('div');
const firstImageWrapper = document.createElement('div');
const secondImageWrapper = document.createElement('div');
const slider = document.createElement('div');
const sliderHandle = document.createElement('div');
const firstLabel = document.createElement('div');
const secondLabel = document.createElement('div');
const arrowLeft = document.createElement('div');
const arrowRight = document.createElement('div');
const firstImgClone = originalImg.cloneNode(true);
firstImgClone.style.width = '100%';
firstImgClone.style.height = '100%';
secondImg.style.width = `${width}px`;
secondImg.style.height = `${height}px`;
secondImg.style.maxWidth = 'none';
sliderHandle.appendChild(arrowLeft);
sliderHandle.appendChild(arrowRight);
slider.appendChild(sliderHandle);
firstImageWrapper.appendChild(firstImgClone);
secondImageWrapper.appendChild(secondImg);
container.appendChild(firstImageWrapper);
container.appendChild(secondImageWrapper);
container.appendChild(firstLabel);
container.appendChild(secondLabel);
container.appendChild(slider);
// --- 3. Style the elements ---
const isHorizontal = orientation.toLowerCase() !== 'vertical';
Object.assign(container.style, {
position: 'relative',
width: `${width}px`,
height: `${height}px`,
overflow: 'hidden',
cursor: 'default',
userSelect: 'none',
fontFamily: 'Arial, sans-serif'
});
Object.assign(firstImageWrapper.style, {
position: 'absolute', top: '0', left: '0', width: '100%', height: '100%', zIndex: '1'
});
Object.assign(secondImageWrapper.style, {
position: 'absolute', top: '0', left: '0', width: '100%', height: '100%', overflow: 'hidden', zIndex: '2'
});
Object.assign(slider.style, {
position: 'absolute',
top: '0',
left: '0',
width: isHorizontal ? '3px' : '100%',
height: isHorizontal ? '100%' : '3px',
background: 'rgba(255, 255, 255, 0.9)',
boxShadow: '0 0 5px rgba(0, 0, 0, 0.5)',
cursor: isHorizontal ? 'ew-resize' : 'ns-resize',
zIndex: '10',
transform: isHorizontal ? 'translateX(-50%)' : 'translateY(-50%)'
});
Object.assign(sliderHandle.style, {
position: 'absolute',
background: 'rgba(255, 255, 255, 0.9)',
border: '3px solid white',
borderRadius: '50%',
boxShadow: '0 0 10px rgba(0,0,0,0.5)',
width: '40px',
height: '40px',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
});
const arrowBaseStyle = {
position: 'absolute',
top: '50%',
left: '50%',
width: '10px',
height: '10px',
borderTop: '3px solid #333',
borderRight: '3px solid #333'
};
Object.assign(arrowLeft.style, arrowBaseStyle);
Object.assign(arrowRight.style, arrowBaseStyle);
if (isHorizontal) {
arrowLeft.style.transform = 'translate(-12px, -50%) rotate(-135deg)';
arrowRight.style.transform = 'translate(2px, -50%) rotate(45deg)';
} else {
arrowLeft.style.transform = 'translate(-50%, -12px) rotate(225deg)'; // up arrow
arrowRight.style.transform = 'translate(-50%, 2px) rotate(45deg)'; // down arrow
}
const labelBaseStyle = {
position: 'absolute',
background: 'rgba(0,0,0,0.7)',
color: 'white',
padding: '8px 12px',
borderRadius: '5px',
pointerEvents: 'none',
zIndex: '5',
fontSize: '14px',
fontWeight: 'bold',
textTransform: 'uppercase'
};
Object.assign(firstLabel.style, labelBaseStyle);
Object.assign(secondLabel.style, labelBaseStyle);
firstLabel.textContent = label1;
secondLabel.textContent = label2;
firstLabel.style.top = '10px';
firstLabel.style.left = '10px';
secondLabel.style.top = '10px';
secondLabel.style.right = '10px';
// --- 4. Interaction Logic ---
const moveSlider = (pos) => {
if (isHorizontal) {
const percentage = Math.max(0, Math.min(100, (pos / width) * 100));
slider.style.left = `${percentage}%`;
secondImageWrapper.style.width = `${percentage}%`;
} else {
const percentage = Math.max(0, Math.min(100, (pos / height) * 100));
slider.style.top = `${percentage}%`;
secondImageWrapper.style.height = `${percentage}%`;
}
};
const doDrag = (e) => {
e.preventDefault();
const rect = container.getBoundingClientRect();
if (isHorizontal) {
const x = (e.touches ? e.touches[0].clientX : e.clientX) - rect.left;
moveSlider(x);
} else {
const y = (e.touches ? e.touches[0].clientY : e.clientY) - rect.top;
moveSlider(y);
}
};
const stopDrag = () => {
window.removeEventListener('mousemove', doDrag);
window.removeEventListener('touchmove', doDrag);
window.removeEventListener('mouseup', stopDrag);
window.removeEventListener('touchend', stopDrag);
};
const startDrag = (e) => {
e.preventDefault();
window.addEventListener('mousemove', doDrag);
window.addEventListener('touchmove', doDrag);
window.addEventListener('mouseup', stopDrag);
window.addEventListener('touchend', stopDrag);
};
slider.addEventListener('mousedown', startDrag);
slider.addEventListener('touchstart', startDrag, { passive: false });
// --- 5. Set initial position and return ---
if (isHorizontal) {
moveSlider(width * (initialPosition / 100));
} else {
moveSlider(height * (initialPosition / 100));
}
return container;
}
Apply Changes