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