update img-slider

This commit is contained in:
2025-07-01 06:01:51 +09:00
parent cf93721bad
commit bc99eb0814
11 changed files with 487 additions and 2 deletions

View File

@ -0,0 +1,123 @@
/**
* Image Comparison Slider
* UE5-style before/after image comparison component
*/
class ImageComparison {
constructor(container) {
this.container = container;
this.slider = container.querySelector('.slider');
this.beforeImg = container.querySelector('.img-before');
this.afterImg = container.querySelector('.img-after');
this.sliderThumb = container.querySelector('.slider-thumb');
this.isDragging = false;
this.containerRect = null;
this.init();
}
init() {
this.bindEvents();
this.updatePosition(50); // Start at 50%
}
bindEvents() {
// Mouse events
this.slider.addEventListener('input', (e) => {
this.updatePosition(e.target.value);
});
this.slider.addEventListener('mousedown', () => {
this.isDragging = true;
document.body.style.userSelect = 'none';
});
document.addEventListener('mouseup', () => {
if (this.isDragging) {
this.isDragging = false;
document.body.style.userSelect = '';
}
});
// Touch events for mobile
this.slider.addEventListener('touchstart', (e) => {
this.isDragging = true;
e.preventDefault();
});
this.slider.addEventListener('touchmove', (e) => {
if (this.isDragging) {
const touch = e.touches[0];
this.containerRect = this.container.getBoundingClientRect();
const x = touch.clientX - this.containerRect.left;
const percentage = Math.max(0, Math.min(100, (x / this.containerRect.width) * 100));
this.slider.value = percentage;
this.updatePosition(percentage);
e.preventDefault();
}
});
this.slider.addEventListener('touchend', () => {
this.isDragging = false;
});
// Direct click on container
this.container.addEventListener('click', (e) => {
if (e.target === this.container || e.target.classList.contains('img-comparison-slider')) {
this.containerRect = this.container.getBoundingClientRect();
const x = e.clientX - this.containerRect.left;
const percentage = Math.max(0, Math.min(100, (x / this.containerRect.width) * 100));
this.slider.value = percentage;
this.updatePosition(percentage);
}
});
// Keyboard support
this.slider.addEventListener('keydown', (e) => {
let value = parseFloat(this.slider.value);
switch (e.key) {
case 'ArrowLeft':
value = Math.max(0, value - 1);
break;
case 'ArrowRight':
value = Math.min(100, value + 1);
break;
case 'Home':
value = 0;
break;
case 'End':
value = 100;
break;
default:
return;
}
e.preventDefault();
this.slider.value = value;
this.updatePosition(value);
});
}
updatePosition(percentage) {
const position = parseFloat(percentage);
// Update clip-path for before image to show only the left portion
this.beforeImg.style.clipPath = `inset(0 ${100 - position}% 0 0)`;
// Update slider thumb position
this.sliderThumb.style.left = `${position}%`;
this.sliderThumb.style.transform = `translateX(-50%)`;
}
}
// Auto-initialize all image comparison components
document.addEventListener('DOMContentLoaded', function() {
const comparisons = document.querySelectorAll('.img-comparison-container');
comparisons.forEach(container => {
new ImageComparison(container);
});
});
// Export for manual initialization
window.ImageComparison = ImageComparison;