Add some delete animation

pull/37/head
Varun Patil 2022-09-08 10:41:16 -07:00
parent e6ac64a240
commit 4abf300350
3 changed files with 91 additions and 3 deletions

View File

@ -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;

View File

@ -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();

View File

@ -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,
}; };