blob: dc83e74535cf4442092bc299261be00039276af2 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
export default class Shadow {
zIndex = '1000'
isOpen = false
/**
* ============
* Constructors
* ============
*/
constructor(image) {
this.create(image);
this.calculateStartsAndFinals();
return this;
}
create(image) {
// create shadow image
const shadowImage = document.createElement('img');
shadowImage.src = image.src;
shadowImage.id = `libra-shadow-${image.id}`;
shadowImage.classList.add('libra-shadow');
// style and position shadow image
shadowImage.style.top = image.offsetTop;
shadowImage.style.left = image.offsetLeft;
shadowImage.style.width = image.offsetWidth;
shadowImage.style.height = image.offsetHeight;
shadowImage.style.zIndex = this.zIndex;
document.body.appendChild(shadowImage);
this.element = shadowImage;
}
calculateStartsAndFinals() {
// get starting state
const s = {
top: this.element.offsetTop,
left: this.element.offsetLeft,
width: this.element.offsetWidth,
height: this.element.offsetHeight
}
const f = {};
const margin = 50;
// calculate final size
const nw = this.element.naturalWidth;
const nh = this.element.naturalHeight;
const ratio = nw / nh;
const ww = window.innerWidth - margin*2;
const wh = window.innerHeight - margin*2;
f.width = Math.min(nw, ww);
f.height = f.width / ratio;
if (f.height >= wh) {
f.height = wh;
f.width = f.height * ratio;
}
// calculate final position
f.left = (ww - f.width) / 2 + margin;
f.top = (wh - f.height) / 2 + margin;
this.finalState = f;
this.startingState = s;
}
/**
* ============
* Actions
* ============
*/
open() {
this.isOpen = true;
this.animate(this.startingState, this.finalState)
}
close() {
this.isOpen = false;
this.animate(this.finalState, this.startingState);
}
animate(starts, finals) {
// Set up the interval for smooth transition
const steps = 20; // Number of steps for smoothness
let step = 0;
// Using requestAnimationFrame for smoother animation
const frame = () => {
// Calculate the progress (from 0 to 1)
const progress = step / steps;
// Interpolate the current values based on progress
const currentTop = starts.top + (finals.top - starts.top) * progress;
const currentLeft = starts.left + (finals.left - starts.left) * progress;
const currentWidth = starts.width + (finals.width - starts.width) * progress;
const currentHeight = starts.height + (finals.height - starts.height) * progress;
// Update the element's style
this.element.style.top = `${currentTop}px`;
this.element.style.left = `${currentLeft}px`;
this.element.style.width = `${currentWidth}px`;
this.element.style.height = `${currentHeight}px`;
// Increase the step count
step++;
// Continue animating until we reach the final step
if (step <= steps) {
requestAnimationFrame(frame);
} else {
this.element.classList.toggle('open');
if (!this.isOpen) this.destroyItself();
}
};
// Start the animation
requestAnimationFrame(frame);
}
placeItself() {
document.body.appendChild(this.element);
}
destroyItself() {
if (!document.body.contains(this.element)) return;
document.body.removeChild(this.element);
}
}
|