Add some delete animation
parent
e6ac64a240
commit
4abf300350
|
@ -1,6 +1,11 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="photo-container"
|
<div class="photo-container"
|
||||||
:class="{ 'selected': (data.flag & c.FLAG_SELECTED) }">
|
:class="{
|
||||||
|
'selected': (data.flag & c.FLAG_SELECTED),
|
||||||
|
'leaving': (data.flag & c.FLAG_LEAVING),
|
||||||
|
'exit-left': (data.flag & c.FLAG_EXIT_LEFT),
|
||||||
|
'enter-right': (data.flag & c.FLAG_ENTER_RIGHT),
|
||||||
|
}">
|
||||||
|
|
||||||
<div class="icon-checkmark select"
|
<div class="icon-checkmark select"
|
||||||
v-if="!(data.flag & c.FLAG_PLACEHOLDER)"
|
v-if="!(data.flag & c.FLAG_PLACEHOLDER)"
|
||||||
|
@ -184,6 +189,31 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
/* Container and selection */
|
||||||
|
.photo-container.leaving {
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
transform: scale(0.9);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
.photo-container.exit-left {
|
||||||
|
transition: all 0.2s ease-in;
|
||||||
|
transform: translateX(-20%);
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
@keyframes enter-right {
|
||||||
|
from {
|
||||||
|
transform: translateX(20%);
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
transform: translateX(0);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.photo-container.enter-right {
|
||||||
|
animation: enter-right 0.2s ease-out forwards;
|
||||||
|
|
||||||
|
}
|
||||||
.photo-container:hover .icon-checkmark {
|
.photo-container:hover .icon-checkmark {
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
|
@ -208,10 +238,13 @@ export default {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extra icons */
|
||||||
.icon-video-white {
|
.icon-video-white {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px; right: 8px;
|
top: 8px; right: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Actual image */
|
||||||
.img-outer {
|
.img-outer {
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
transition: all 0.1s ease-in-out;
|
transition: all 0.1s ease-in-out;
|
||||||
|
|
|
@ -724,6 +724,35 @@ export default {
|
||||||
await Promise.allSettled(promises);
|
await Promise.allSettled(promises);
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
|
||||||
|
// Animate the deletion
|
||||||
|
for (const photo of this.selection) {
|
||||||
|
if (delIds.has(photo.fileid)) {
|
||||||
|
photo.flag |= constants.FLAG_LEAVING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for 250ms
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
|
||||||
|
// Speculate day reflow for animation
|
||||||
|
const exitedLeft = new Set();
|
||||||
|
for (const day of updatedDays) {
|
||||||
|
let nextExit = false;
|
||||||
|
for (const row of day.rows) {
|
||||||
|
for (const photo of row.photos) {
|
||||||
|
if (photo.flag & constants.FLAG_LEAVING) {
|
||||||
|
nextExit = true;
|
||||||
|
} else if (nextExit) {
|
||||||
|
photo.flag |= constants.FLAG_EXIT_LEFT;
|
||||||
|
exitedLeft.add(photo.fileid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for 200ms
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
|
||||||
// Reflow all touched days
|
// Reflow all touched days
|
||||||
for (const day of updatedDays) {
|
for (const day of updatedDays) {
|
||||||
day.detail = day.detail.filter(p => !delIds.has(p.fileid));
|
day.detail = day.detail.filter(p => !delIds.has(p.fileid));
|
||||||
|
@ -731,6 +760,29 @@ export default {
|
||||||
this.processDay(day);
|
this.processDay(day);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enter from right all photos that exited left
|
||||||
|
for (const day of updatedDays) {
|
||||||
|
for (const row of day.rows) {
|
||||||
|
for (const photo of row.photos) {
|
||||||
|
if (exitedLeft.has(photo.fileid)) {
|
||||||
|
photo.flag |= constants.FLAG_ENTER_RIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for 200ms
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 200));
|
||||||
|
|
||||||
|
// Clear enter right flags
|
||||||
|
for (const day of updatedDays) {
|
||||||
|
for (const row of day.rows) {
|
||||||
|
for (const photo of row.photos) {
|
||||||
|
photo.flag &= ~constants.FLAG_ENTER_RIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.clearSelection();
|
this.clearSelection();
|
||||||
this.reflowTimeline();
|
this.reflowTimeline();
|
||||||
this.handleViewSizeChange();
|
this.handleViewSizeChange();
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
export default {
|
export default {
|
||||||
FLAG_PLACEHOLDER: 1,
|
FLAG_PLACEHOLDER: 1 << 0,
|
||||||
FLAG_SELECTED: 2,
|
FLAG_SELECTED: 1 << 1,
|
||||||
|
FLAG_LEAVING: 1 << 2,
|
||||||
|
FLAG_EXIT_LEFT: 1 << 3,
|
||||||
|
FLAG_ENTER_RIGHT: 1 << 4,
|
||||||
};
|
};
|
Loading…
Reference in New Issue