Add easing towards the different element
Browse files- assets/scripts/src/overlay.js +93 -22
- assets/scripts/src/position.js +1 -1
- index.html +1 -2
assets/scripts/src/overlay.js
CHANGED
@@ -5,10 +5,14 @@ import Position from './position';
|
|
5 |
* cutting out the visible part, animating between the sections etc
|
6 |
*/
|
7 |
export default class Overlay {
|
8 |
-
constructor({
|
9 |
-
this.
|
10 |
-
this.
|
11 |
-
this.
|
|
|
|
|
|
|
|
|
12 |
|
13 |
this.window = window;
|
14 |
this.document = document;
|
@@ -40,11 +44,12 @@ export default class Overlay {
|
|
40 |
|
41 |
// get the position of element around which we need to draw
|
42 |
const position = element.getPosition();
|
43 |
-
if (!position.
|
44 |
return;
|
45 |
}
|
46 |
|
47 |
-
this.
|
|
|
48 |
this.draw();
|
49 |
}
|
50 |
|
@@ -52,24 +57,90 @@ export default class Overlay {
|
|
52 |
this.document.body.removeChild(this.overlay);
|
53 |
}
|
54 |
|
|
|
|
|
|
|
|
|
|
|
55 |
draw() {
|
56 |
-
//
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
72 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
73 |
}
|
74 |
|
75 |
setSize(width = null, height = null) {
|
|
|
5 |
* cutting out the visible part, animating between the sections etc
|
6 |
*/
|
7 |
export default class Overlay {
|
8 |
+
constructor({ opacity = 0.75 }) {
|
9 |
+
this.opacity = opacity;
|
10 |
+
this.overlayAlpha = 0;
|
11 |
+
this.positionToHighlight = new Position({});
|
12 |
+
this.highlightedPosition = new Position({});
|
13 |
+
this.redrawAnimation = null;
|
14 |
+
|
15 |
+
this.draw = this.draw.bind(this);
|
16 |
|
17 |
this.window = window;
|
18 |
this.document = document;
|
|
|
44 |
|
45 |
// get the position of element around which we need to draw
|
46 |
const position = element.getPosition();
|
47 |
+
if (!position.canHighlight()) {
|
48 |
return;
|
49 |
}
|
50 |
|
51 |
+
this.highlightedElement = element;
|
52 |
+
this.positionToHighlight = position;
|
53 |
this.draw();
|
54 |
}
|
55 |
|
|
|
57 |
this.document.body.removeChild(this.overlay);
|
58 |
}
|
59 |
|
60 |
+
/**
|
61 |
+
* `draw` is called for in requestAnimationFrame. Here is what it does
|
62 |
+
* - Puts back the filled overlay on body (i.e. while clearing existing highlight if any)
|
63 |
+
* - Slowly eases towards the item to be selected
|
64 |
+
*/
|
65 |
draw() {
|
66 |
+
// Cache the response of this for re-use below
|
67 |
+
const canHighlight = this.positionToHighlight.canHighlight();
|
68 |
+
|
69 |
+
// Remove the existing cloak from the body
|
70 |
+
// it might be torn i.e. have patches from last highlight
|
71 |
+
this.removeCloak();
|
72 |
+
// Add the overlay on top of the whole body
|
73 |
+
this.addCloak();
|
74 |
+
|
75 |
+
if (canHighlight) {
|
76 |
+
const isFadingIn = this.overlayAlpha < 0.1;
|
77 |
+
|
78 |
+
if (isFadingIn) {
|
79 |
+
// Ignore the animation, just highlight the item
|
80 |
+
this.highlightedPosition = this.positionToHighlight;
|
81 |
+
} else {
|
82 |
+
// Slowly move towards the position to highlight
|
83 |
+
this.highlightedPosition.left += (this.positionToHighlight.left - this.highlightedPosition.left) * 0.18;
|
84 |
+
this.highlightedPosition.top += (this.positionToHighlight.top - this.highlightedPosition.top) * 0.18;
|
85 |
+
this.highlightedPosition.right += (this.positionToHighlight.right - this.highlightedPosition.right) * 0.18;
|
86 |
+
this.highlightedPosition.bottom += (this.positionToHighlight.bottom - this.highlightedPosition.bottom) * 0.18;
|
87 |
+
}
|
88 |
}
|
89 |
+
|
90 |
+
// Remove the cloak from the position to highlight
|
91 |
+
this.removeCloak({
|
92 |
+
posX: this.highlightedPosition.left - window.scrollX - 5,
|
93 |
+
posY: this.highlightedPosition.top - window.scrollY - 5,
|
94 |
+
width: (this.highlightedPosition.right - this.highlightedPosition.left) + (5 * 2),
|
95 |
+
height: (this.highlightedPosition.bottom - this.highlightedPosition.top) + (5 * 2),
|
96 |
+
});
|
97 |
+
|
98 |
+
if (canHighlight) {
|
99 |
+
// Fade the overlay in if we can highlight
|
100 |
+
this.overlayAlpha += (this.opacity - this.overlayAlpha) * 0.08;
|
101 |
+
} else {
|
102 |
+
// otherwise fade out
|
103 |
+
this.overlayAlpha = Math.max((this.overlayAlpha * 0.85) - 0.02, 0);
|
104 |
+
}
|
105 |
+
|
106 |
+
// cancel any existing animation frames
|
107 |
+
// to avoid the overlapping of frames
|
108 |
+
this.window.cancelAnimationFrame(this.redrawAnimation);
|
109 |
+
|
110 |
+
// Continue drawing while we can highlight or we are still fading out
|
111 |
+
if (canHighlight || this.overlayAlpha > 0) {
|
112 |
+
console.log(this.overlayAlpha);
|
113 |
+
// Add the overlay if not already there
|
114 |
+
if (!this.overlay.parentNode) {
|
115 |
+
document.body.appendChild(this.overlay);
|
116 |
+
}
|
117 |
+
|
118 |
+
// Stage a new animation frame
|
119 |
+
this.redrawAnimation = this.window.requestAnimationFrame(this.draw);
|
120 |
+
} else {
|
121 |
+
this.document.body.removeChild(this.overlay);
|
122 |
+
}
|
123 |
+
}
|
124 |
+
|
125 |
+
// Removes the patch of given width and height from the given position (x,y)
|
126 |
+
removeCloak({
|
127 |
+
posX = 0,
|
128 |
+
posY = 0,
|
129 |
+
width = this.overlay.width,
|
130 |
+
height = this.overlay.height,
|
131 |
+
} = {}) {
|
132 |
+
this.context.clearRect(posX, posY, width, height);
|
133 |
+
}
|
134 |
+
|
135 |
+
// Adds the cloak i.e. covers the given position with dark overlay
|
136 |
+
addCloak({
|
137 |
+
posX = 0,
|
138 |
+
posY = 0,
|
139 |
+
width = this.overlay.width,
|
140 |
+
height = this.overlay.height,
|
141 |
+
} = {}) {
|
142 |
+
this.context.fillStyle = `rgba( 0, 0, 0, ${this.overlayAlpha} )`;
|
143 |
+
this.context.fillRect(posX, posY, width, height);
|
144 |
}
|
145 |
|
146 |
setSize(width = null, height = null) {
|
assets/scripts/src/position.js
CHANGED
@@ -21,7 +21,7 @@ export default class Position {
|
|
21 |
this.bottom = bottom;
|
22 |
}
|
23 |
|
24 |
-
|
25 |
return this.left < this.right && this.top < this.bottom;
|
26 |
}
|
27 |
}
|
|
|
21 |
this.bottom = bottom;
|
22 |
}
|
23 |
|
24 |
+
canHighlight() {
|
25 |
return this.left < this.right && this.top < this.bottom;
|
26 |
}
|
27 |
}
|
index.html
CHANGED
@@ -46,7 +46,6 @@
|
|
46 |
<script>
|
47 |
const nodesToSelect = [
|
48 |
'.section__header',
|
49 |
-
'asdfsfd',
|
50 |
'.section__how',
|
51 |
'.section__examples'
|
52 |
];
|
@@ -56,7 +55,7 @@
|
|
56 |
nodesToSelect.forEach((nodeToSelect, index) => {
|
57 |
window.setTimeout(() => {
|
58 |
sholo.highlight(nodeToSelect);
|
59 |
-
}, index *
|
60 |
});
|
61 |
</script>
|
62 |
</body>
|
|
|
46 |
<script>
|
47 |
const nodesToSelect = [
|
48 |
'.section__header',
|
|
|
49 |
'.section__how',
|
50 |
'.section__examples'
|
51 |
];
|
|
|
55 |
nodesToSelect.forEach((nodeToSelect, index) => {
|
56 |
window.setTimeout(() => {
|
57 |
sholo.highlight(nodeToSelect);
|
58 |
+
}, index * 1000);
|
59 |
});
|
60 |
</script>
|
61 |
</body>
|