1. デザインのタイプ
【インタラクティブ・イメージ比較スライダー】
2枚の画像を重ね、ユーザーが境界線を左右にドラッグすることで、変化(Before/After)を直感的に比較できるデザイン。リアルタイムな視覚フィードバックにより、加工効果やビフォーアフターの差異を劇的に演出します。
2. デザインの特徴
- リアルタイム・マスキング処理
左側の画像を動的にクリッピングすることで、左右の画像の解像度や拡大率を完全に一致させたまま比較が可能。 - ハイブリッド・レスポンシブ
PCでは境界線のドラッグ、スマホでは画像全体のタッチ操作に対応し、デバイスを問わずスムーズに動作。 - 視覚的ガイド・UI
境界線中央に配置されたダブルアローアイコンにより、直感的な操作感と高い視認性を実現。
3. 紹介コード
<div class="comparison-block" id="comparison-slider">
<span class="comparison-arrow"></span>
<div class="comparison-before-img">
<img src="画像URL" alt="加工前の写真(左側の写真)">
</div>
<div class="comparison-after-img">
<img src="画像URL" alt="加工後の写真(右側の写真)">
</div>
</div>
<style>
/* --- スライダーのスタイル --- */
.comparison-block {
width: 100%;
max-width: 640px;
position: relative;
margin: 20px auto;
overflow: hidden;
user-select: none;
-webkit-user-select: none;
line-height: 0;
}
.comparison-block::selection, .comparison-block *::selection { background-color: transparent; }
.comparison-block::-moz-selection, .comparison-block *::-moz-selection { background-color: transparent; }
.comparison-before-img {
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
overflow: hidden;
z-index: 5;
}
.comparison-before-img img {
height: 100% !important;
width: auto !important;
display: block;
max-width: none !important;
object-fit: cover;
object-position: left center;
}
.comparison-after-img {
position: relative;
z-index: 1;
}
.comparison-after-img img {
width: 100%;
height: auto;
display: block;
}
.comparison-arrow {
background-color: #fff;
position: absolute;
z-index: 10;
top: 0;
width: 2px;
height: 100%;
left: 50%;
cursor: ew-resize;
}
.comparison-arrow:after {
content: '';
display: block;
width: 34px;
height: 34px;
border-radius: 50%;
background-color: #fff;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="%23333" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><polyline points="11 17 6 12 11 7"/><polyline points="13 17 18 12 13 7"/></svg>');
background-repeat: no-repeat;
background-position: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}
</style>
<script>
// <![CDATA[
(function() {
const blockElements = document.getElementsByClassName('comparison-block');
const arrows = document.getElementsByClassName('comparison-arrow');
const beforeDivs = document.getElementsByClassName('comparison-before-img');
let device = (navigator.userAgent.match(/(iPhone|iPod|iPad|Android|Windows Phone)/)) ? 'smt' : 'pc';
let startEvent = (device === 'smt') ? 'touchstart' : 'mousedown';
let moveEvent = (device === 'smt') ? 'touchmove' : 'mousemove';
let endEvent = (device === 'smt') ? 'touchend' : 'mouseup';
let isDragging = false;
let activeSlider = null;
function initLayout() {
for (let i = 0; i < blockElements.length; i++) {
let width = blockElements[i].clientWidth;
let beforeImg = beforeDivs[i].querySelector('img');
if (beforeImg) {
beforeImg.style.width = width + 'px';
}
beforeDivs[i].style.width = (width / 2) + 'px';
arrows[i].style.left = (width / 2) + 'px';
}
}
function onStart(e) {
isDragging = true;
activeSlider = this.closest('.comparison-block');
if (device === 'pc') {
window.addEventListener(moveEvent, onMove);
} else {
activeSlider.addEventListener(moveEvent, onMove, { passive: false });
}
}
function onMove(e) {
if (!isDragging || !activeSlider) return;
let event = (device === 'smt') ? e.changedTouches[0] : e;
let rect = activeSlider.getBoundingClientRect();
let arrow = activeSlider.querySelector('.comparison-arrow');
let beforeDiv = activeSlider.querySelector('.comparison-before-img');
let x = event.pageX - (rect.left + window.pageXOffset);
let maxX = activeSlider.clientWidth;
if (x < 0) x = 0;
if (x > maxX) x = maxX;
arrow.style.left = x + 'px';
beforeDiv.style.width = x + 'px';
if (device === 'smt') e.preventDefault();
}
function onEnd() {
isDragging = false;
if (activeSlider && device === 'smt') {
activeSlider.removeEventListener(moveEvent, onMove);
}
window.removeEventListener(moveEvent, onMove);
activeSlider = null;
}
window.addEventListener('load', initLayout);
window.addEventListener('resize', initLayout);
for (let i = 0; i < blockElements.length; i++) {
let target = (device === 'smt') ? blockElements[i] : arrows[i];
target.addEventListener(startEvent, onStart);
}
window.addEventListener(endEvent, onEnd);
})();
// ]]>
</script>




コメントを投稿