viewimage page alignment finish

This commit is contained in:
Chaebean Yang 2025-06-10 00:16:06 +09:00
parent ea01ae074e
commit 06cfd4dad8

View File

@ -15,6 +15,14 @@
let columnGroups = []; let columnGroups = [];
let rotationAngle = 0; let rotationAngle = 0;
let droppedTripId = null;
let droppedMemory = null;
let droppedImageIndex = 0;
let droppedColumnGroups = [];
let droppedGradientLayers = [];
let droppedWheelStyle = {};
let droppedCurrentImage = null;
$: tripId = $page.params.tripId; $: tripId = $page.params.tripId;
$: memoryId = $page.params.memoryId; $: memoryId = $page.params.memoryId;
$: currentImage = memory?.images?.[currentImageIndex]; $: currentImage = memory?.images?.[currentImageIndex];
@ -70,10 +78,19 @@
} }
} }
async function loadDroppedTrip(tripId, memoryId) {
const memorySnap = await get(ref(db, `trips/${tripId}/memories/${memoryId}`));
if (memorySnap.exists()) {
droppedTripId = tripId;
droppedMemory = memorySnap.val();
droppedColumnGroups = await extractColumnwiseColors(droppedMemory.images);
droppedImageIndex = 0;
}
}
$: { $: {
if (memory?.images?.length > 0) { if (memory?.images?.length > 0) {
const imageCount = memory.images.length; const sliceAngle = 360 / memory.images.length;
const sliceAngle = 360 / imageCount;
rotationAngle = sliceAngle * currentImageIndex - 90; rotationAngle = sliceAngle * currentImageIndex - 90;
} else { } else {
rotationAngle = 0; rotationAngle = 0;
@ -192,6 +209,34 @@
}); });
} }
$: if (droppedMemory?.images?.length && droppedColumnGroups.length) {
const angleOffset = -(360 / droppedMemory.images.length) * droppedImageIndex;
const gradients = makeConcentricGradients(droppedColumnGroups, angleOffset);
const MASK_COUNT = 3;
for (let i = 0; i < MASK_COUNT; i++) {
gradients.push('radial-gradient(circle, var(--black) 100%)');
}
droppedGradientLayers = gradients.map((bg, i) => {
const scale = 1 - i * 0.1;
return `background: ${bg};
width: ${scale * 100}%;
height: ${scale * 100}%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
border-radius: 50%;`;
});
droppedWheelStyle = {
transform: `translateY(-50%) rotate(${-90 + (360 / droppedMemory.images.length) * droppedImageIndex}deg)`
};
droppedCurrentImage = droppedMemory.images[droppedImageIndex];
}
function nextImage() { function nextImage() {
if (memory?.images?.length > 0) { if (memory?.images?.length > 0) {
currentImageIndex = (currentImageIndex + 1) % memory.images.length; currentImageIndex = (currentImageIndex + 1) % memory.images.length;
@ -203,6 +248,29 @@
currentImageIndex = (currentImageIndex - 1 + memory.images.length) % memory.images.length; currentImageIndex = (currentImageIndex - 1 + memory.images.length) % memory.images.length;
} }
} }
function nextDroppedImage() {
if (droppedMemory?.images?.length > 0) {
droppedImageIndex = (droppedImageIndex + 1) % droppedMemory.images.length;
}
}
function prevDroppedImage() {
if (droppedMemory?.images?.length > 0) {
droppedImageIndex = (droppedImageIndex - 1 + droppedMemory.images.length) % droppedMemory.images.length;
}
}
function handleDrop(event) {
event.preventDefault();
const droppedTripId = event.dataTransfer.getData("tripId");
const droppedMemoryId = event.dataTransfer.getData("memoryId");
loadDroppedTrip(droppedTripId, droppedMemoryId);
}
function allowDrop(event) {
event.preventDefault();
}
</script> </script>
@ -220,6 +288,11 @@
{#each tripOptions as trip} {#each tripOptions as trip}
<button <button
class={trip.id === tripId ? 'active' : ''} class={trip.id === tripId ? 'active' : ''}
draggable="true"
on:dragstart={(e) => {
e.dataTransfer.setData('tripId', trip.id);
e.dataTransfer.setData('memoryId', trip.memoryId);
}}
on:click={() => goto(`/viewimage/${trip.id}/${trip.memoryId}`)}> on:click={() => goto(`/viewimage/${trip.id}/${trip.memoryId}`)}>
{trip.label} {trip.label}
</button> </button>
@ -227,22 +300,45 @@
</div> </div>
</div> </div>
<div class="wheel-container"> <div class="wheel-compare-wrapper">
<div class="wheel-mask"> <!-- leftside original wheel -->
<div class="gradient-wheel" style={wheelStyle}> <div class="wheel-section">
{#each gradientLayers as style} <div class="wheel-mask">
<div class="layer" style={style}></div> <div class="gradient-wheel" style={wheelStyle}>
{/each} {#each gradientLayers as style}
<div class="layer" style={style}></div>
{/each}
</div>
</div>
{#if currentImage}
<img class="preview-img" src={currentImage} alt="Current Image" />
{/if}
<div class="arrow-controls">
<button on:click={prevImage}>▲</button>
<button on:click={nextImage}>▼</button>
</div> </div>
</div> </div>
{#if currentImage} <!-- rightside dropped view -->
<img class="preview-img" src={currentImage} alt="Current Image" /> <div class="wheel-section drop-zone" on:drop={handleDrop} on:dragover={allowDrop}>
{/if} {#if droppedMemory}
<div class="dropped-mask">
<div class="arrow-controls"> <div class="dropped-wheel" style={droppedWheelStyle}>
<button on:click={prevImage}>▲</button> {#each droppedGradientLayers as style}
<button on:click={nextImage}>▼</button> <div class="layer" style={style}></div>
{/each}
</div>
</div>
{#if droppedCurrentImage}
<img class="dropped-img" src={droppedCurrentImage} alt="Dropped Image" />
{/if}
<div class="dropped-controls">
<button on:click={prevDroppedImage}>▲</button>
<button on:click={nextDroppedImage}>▼</button>
</div>
{/if}
</div> </div>
</div> </div>
{/if} {/if}
@ -252,6 +348,7 @@
<style> <style>
main { main {
height: 100vh; height: 100vh;
width: 100vw;
background-color: var(--black); background-color: var(--black);
font-family: 'Inter', sans-serif; font-family: 'Inter', sans-serif;
display: flex; display: flex;
@ -259,16 +356,16 @@
} }
.content { .content {
flex: 1; padding: 0;
padding: 0 1rem 2rem 1rem;
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100vw;
} }
.header { .header {
padding-top: 2rem; padding-top: 2rem;
padding-left: 1rem; padding-left: 2rem;
background-color: var(--black); background-color: var(--black);
color: var(--white); color: var(--white);
} }
@ -282,8 +379,8 @@
.trip-switcher { .trip-switcher {
width: 100%; width: 100%;
text-align: center; text-align: center;
overflow: hidden;
padding-top: 1.5rem; padding-top: 1.5rem;
padding-left: 2rem;
} }
.trip-switcher-inner { .trip-switcher-inner {
@ -342,29 +439,36 @@
transition: transform 0.2s ease; transition: transform 0.2s ease;
} }
.wheel-container { .wheel-compare-wrapper {
display: flex;
justify-content: space-between;
margin-top: 2rem;
width: 100%;
height: 100%;
}
.wheel-section {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 20px; gap: 32px;
margin-top: 2rem; width: 50%;
height: 40vw;
position: relative; position: relative;
} }
.wheel-mask { .wheel-mask {
width: 50vw; display: flex;
height: 100%; width: 20vw;
height: 35vw;
overflow: hidden; overflow: hidden;
position: relative; position: relative;
align-items: center;
} }
.gradient-wheel { .gradient-wheel {
position: absolute; position: absolute;
width: 35vw; width: 35vw;
height: 35vw; height: 35vw;
left: -17.5vw; left: -15vw;
top: 50%;
transform: translateY(-50%);
border-radius: 50%; border-radius: 50%;
} }
@ -377,10 +481,7 @@
} }
.preview-img { .preview-img {
position: absolute; position: relative;
top: 50%;
left: calc(17.5vw + 180px);
transform: translate(-50%, -50%);
width: 300px; width: 300px;
height: 200px; height: 200px;
object-fit: cover; object-fit: cover;
@ -391,10 +492,7 @@
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 20px; gap: 20px;
position: absolute; position: relative;
top: 50%;
left: calc(17.5vw + 340px);
transform: translateY(-50%);
z-index: 4; z-index: 4;
} }
@ -405,5 +503,55 @@
color: white; color: white;
cursor: pointer; cursor: pointer;
} }
.wheel-section.drop-zone {
display: flex;
flex-direction: row-reverse;
align-items: center;
gap: 32px;
width: 50%;
position: relative;
}
.dropped-controls {
display: flex;
flex-direction: column;
gap: 20px;
position: relative;
z-index: 4;
}
.dropped-controls button {
background: none;
border: none;
font-size: 1.5rem;
color: white;
cursor: pointer;
}
.dropped-img {
position: relative;
width: 300px;
height: 200px;
object-fit: cover;
z-index: 3;
}
.dropped-mask {
display: flex;
width: 20vw;
height: 35vw;
overflow: hidden;
position: relative;
align-items: center;
}
.dropped-wheel {
position: absolute;
width: 35vw;
height: 35vw;
right: -15vw;
border-radius: 50%;
}
</style> </style>