Add docs and refactor
Browse files- assets/scripts/src/element.js +13 -3
- assets/scripts/src/overlay.js +54 -13
- assets/scripts/src/position.js +13 -4
- assets/scripts/src/sholo.js +27 -2
- index.html +2 -16
assets/scripts/src/element.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
| 1 |
import Position from './position';
|
| 2 |
|
| 3 |
export default class Element {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
constructor(node) {
|
| 5 |
this.element = node;
|
| 6 |
this.document = document;
|
| 7 |
}
|
| 8 |
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
| 10 |
getScreenCoordinates() {
|
| 11 |
let tempNode = this.element;
|
| 12 |
|
|
@@ -23,8 +30,11 @@ export default class Element {
|
|
| 23 |
return { x, y };
|
| 24 |
}
|
| 25 |
|
| 26 |
-
|
| 27 |
-
|
|
|
|
|
|
|
|
|
|
| 28 |
const coordinates = this.getScreenCoordinates();
|
| 29 |
const position = new Position({
|
| 30 |
left: Number.MAX_VALUE,
|
|
|
|
| 1 |
import Position from './position';
|
| 2 |
|
| 3 |
export default class Element {
|
| 4 |
+
/**
|
| 5 |
+
* DOM element object
|
| 6 |
+
* @param node
|
| 7 |
+
*/
|
| 8 |
constructor(node) {
|
| 9 |
this.element = node;
|
| 10 |
this.document = document;
|
| 11 |
}
|
| 12 |
|
| 13 |
+
/**
|
| 14 |
+
* Gets the screen co-ordinates (x,y) for the current dom element
|
| 15 |
+
* @returns {{x: number, y: number}}
|
| 16 |
+
*/
|
| 17 |
getScreenCoordinates() {
|
| 18 |
let tempNode = this.element;
|
| 19 |
|
|
|
|
| 30 |
return { x, y };
|
| 31 |
}
|
| 32 |
|
| 33 |
+
/**
|
| 34 |
+
* Gets the calculated position on screen, around which
|
| 35 |
+
* we need to draw
|
| 36 |
+
*/
|
| 37 |
+
getCalculatedPosition() {
|
| 38 |
const coordinates = this.getScreenCoordinates();
|
| 39 |
const position = new Position({
|
| 40 |
left: Number.MAX_VALUE,
|
assets/scripts/src/overlay.js
CHANGED
|
@@ -5,6 +5,11 @@ import Position from './position';
|
|
| 5 |
* cutting out the visible part, animating between the sections etc
|
| 6 |
*/
|
| 7 |
export default class Overlay {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
constructor({
|
| 9 |
opacity = 0.75,
|
| 10 |
padding = 10,
|
|
@@ -29,7 +34,9 @@ export default class Overlay {
|
|
| 29 |
this.setSize();
|
| 30 |
}
|
| 31 |
|
| 32 |
-
|
|
|
|
|
|
|
| 33 |
prepareContext() {
|
| 34 |
const overlay = this.document.createElement('canvas');
|
| 35 |
|
|
@@ -44,14 +51,18 @@ export default class Overlay {
|
|
| 44 |
this.overlay.style.zIndex = '999999999';
|
| 45 |
}
|
| 46 |
|
| 47 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
highlight(element, animate = true) {
|
| 49 |
if (!element) {
|
| 50 |
return;
|
| 51 |
}
|
| 52 |
|
| 53 |
// get the position of element around which we need to draw
|
| 54 |
-
const position = element.
|
| 55 |
if (!position.canHighlight()) {
|
| 56 |
return;
|
| 57 |
}
|
|
@@ -68,6 +79,9 @@ export default class Overlay {
|
|
| 68 |
this.draw();
|
| 69 |
}
|
| 70 |
|
|
|
|
|
|
|
|
|
|
| 71 |
clear() {
|
| 72 |
this.positionToHighlight = new Position();
|
| 73 |
this.highlightedElement = null;
|
|
@@ -81,9 +95,9 @@ export default class Overlay {
|
|
| 81 |
}
|
| 82 |
|
| 83 |
/**
|
| 84 |
-
* `draw` is called for in requestAnimationFrame.
|
| 85 |
-
*
|
| 86 |
-
*
|
| 87 |
*/
|
| 88 |
draw() {
|
| 89 |
// Cache the response of this for re-use below
|
|
@@ -99,7 +113,7 @@ export default class Overlay {
|
|
| 99 |
const isFadingIn = this.overlayAlpha < 0.1;
|
| 100 |
|
| 101 |
if (isFadingIn) {
|
| 102 |
-
// Ignore the animation, just highlight the item
|
| 103 |
this.highlightedPosition = this.positionToHighlight;
|
| 104 |
} else {
|
| 105 |
// Slowly move towards the position to highlight
|
|
@@ -110,7 +124,7 @@ export default class Overlay {
|
|
| 110 |
}
|
| 111 |
}
|
| 112 |
|
| 113 |
-
//
|
| 114 |
this.removeCloak({
|
| 115 |
posX: this.highlightedPosition.left - window.scrollX - this.padding,
|
| 116 |
posY: this.highlightedPosition.top - window.scrollY - this.padding,
|
|
@@ -118,8 +132,8 @@ export default class Overlay {
|
|
| 118 |
height: (this.highlightedPosition.bottom - this.highlightedPosition.top) + (this.padding * 2),
|
| 119 |
});
|
| 120 |
|
|
|
|
| 121 |
if (canHighlight) {
|
| 122 |
-
// Fade the overlay in if we can highlight
|
| 123 |
if (!this.animate) {
|
| 124 |
this.overlayAlpha = this.opacity;
|
| 125 |
} else {
|
|
@@ -154,7 +168,16 @@ export default class Overlay {
|
|
| 154 |
}
|
| 155 |
}
|
| 156 |
|
| 157 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
removeCloak({
|
| 159 |
posX = 0,
|
| 160 |
posY = 0,
|
|
@@ -164,7 +187,15 @@ export default class Overlay {
|
|
| 164 |
this.context.clearRect(posX, posY, width, height);
|
| 165 |
}
|
| 166 |
|
| 167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
addCloak({
|
| 169 |
posX = 0,
|
| 170 |
posY = 0,
|
|
@@ -175,6 +206,12 @@ export default class Overlay {
|
|
| 175 |
this.context.fillRect(posX, posY, width, height);
|
| 176 |
}
|
| 177 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
setSize(width = null, height = null) {
|
| 179 |
// By default it is going to cover the whole page and then we will
|
| 180 |
// cut out a chunk for the element to be visible out of it
|
|
@@ -182,8 +219,12 @@ export default class Overlay {
|
|
| 182 |
this.overlay.height = height || this.window.innerHeight;
|
| 183 |
}
|
| 184 |
|
| 185 |
-
|
| 186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
refresh(animate = true) {
|
| 188 |
this.setSize();
|
| 189 |
|
|
|
|
| 5 |
* cutting out the visible part, animating between the sections etc
|
| 6 |
*/
|
| 7 |
export default class Overlay {
|
| 8 |
+
/**
|
| 9 |
+
* @param opacity number
|
| 10 |
+
* @param padding number
|
| 11 |
+
* @param animate bool
|
| 12 |
+
*/
|
| 13 |
constructor({
|
| 14 |
opacity = 0.75,
|
| 15 |
padding = 10,
|
|
|
|
| 34 |
this.setSize();
|
| 35 |
}
|
| 36 |
|
| 37 |
+
/**
|
| 38 |
+
* Prepares the overlay
|
| 39 |
+
*/
|
| 40 |
prepareContext() {
|
| 41 |
const overlay = this.document.createElement('canvas');
|
| 42 |
|
|
|
|
| 51 |
this.overlay.style.zIndex = '999999999';
|
| 52 |
}
|
| 53 |
|
| 54 |
+
/**
|
| 55 |
+
* Highlights the dom element on the screen
|
| 56 |
+
* @param element Element
|
| 57 |
+
* @param animate bool
|
| 58 |
+
*/
|
| 59 |
highlight(element, animate = true) {
|
| 60 |
if (!element) {
|
| 61 |
return;
|
| 62 |
}
|
| 63 |
|
| 64 |
// get the position of element around which we need to draw
|
| 65 |
+
const position = element.getCalculatedPosition();
|
| 66 |
if (!position.canHighlight()) {
|
| 67 |
return;
|
| 68 |
}
|
|
|
|
| 79 |
this.draw();
|
| 80 |
}
|
| 81 |
|
| 82 |
+
/**
|
| 83 |
+
* Removes the overlay and cancel any listeners
|
| 84 |
+
*/
|
| 85 |
clear() {
|
| 86 |
this.positionToHighlight = new Position();
|
| 87 |
this.highlightedElement = null;
|
|
|
|
| 95 |
}
|
| 96 |
|
| 97 |
/**
|
| 98 |
+
* `draw` is called for in requestAnimationFrame. Puts back the
|
| 99 |
+
* filled overlay on body (i.e. while removing existing highlight if any) and
|
| 100 |
+
* Slowly eases towards the item to be selected.
|
| 101 |
*/
|
| 102 |
draw() {
|
| 103 |
// Cache the response of this for re-use below
|
|
|
|
| 113 |
const isFadingIn = this.overlayAlpha < 0.1;
|
| 114 |
|
| 115 |
if (isFadingIn) {
|
| 116 |
+
// Ignore the animation, just highlight the item at its current position
|
| 117 |
this.highlightedPosition = this.positionToHighlight;
|
| 118 |
} else {
|
| 119 |
// Slowly move towards the position to highlight
|
|
|
|
| 124 |
}
|
| 125 |
}
|
| 126 |
|
| 127 |
+
// Cut the chunk of overlay that is over the highlighted item
|
| 128 |
this.removeCloak({
|
| 129 |
posX: this.highlightedPosition.left - window.scrollX - this.padding,
|
| 130 |
posY: this.highlightedPosition.top - window.scrollY - this.padding,
|
|
|
|
| 132 |
height: (this.highlightedPosition.bottom - this.highlightedPosition.top) + (this.padding * 2),
|
| 133 |
});
|
| 134 |
|
| 135 |
+
// Fade the overlay in if we can highlight
|
| 136 |
if (canHighlight) {
|
|
|
|
| 137 |
if (!this.animate) {
|
| 138 |
this.overlayAlpha = this.opacity;
|
| 139 |
} else {
|
|
|
|
| 168 |
}
|
| 169 |
}
|
| 170 |
|
| 171 |
+
/**
|
| 172 |
+
* Removes the cloak from the given position
|
| 173 |
+
* i.e. cuts the chunk of layout which is over the element
|
| 174 |
+
* to be highlighted
|
| 175 |
+
*
|
| 176 |
+
* @param posX number
|
| 177 |
+
* @param posY number
|
| 178 |
+
* @param width number
|
| 179 |
+
* @param height number
|
| 180 |
+
*/
|
| 181 |
removeCloak({
|
| 182 |
posX = 0,
|
| 183 |
posY = 0,
|
|
|
|
| 187 |
this.context.clearRect(posX, posY, width, height);
|
| 188 |
}
|
| 189 |
|
| 190 |
+
/**
|
| 191 |
+
* Adds the overlay i.e. to cover the given
|
| 192 |
+
* position with dark overlay
|
| 193 |
+
*
|
| 194 |
+
* @param posX number
|
| 195 |
+
* @param posY number
|
| 196 |
+
* @param width number
|
| 197 |
+
* @param height number
|
| 198 |
+
*/
|
| 199 |
addCloak({
|
| 200 |
posX = 0,
|
| 201 |
posY = 0,
|
|
|
|
| 206 |
this.context.fillRect(posX, posY, width, height);
|
| 207 |
}
|
| 208 |
|
| 209 |
+
/**
|
| 210 |
+
* Sets the size for the overlay
|
| 211 |
+
*
|
| 212 |
+
* @param width number
|
| 213 |
+
* @param height number
|
| 214 |
+
*/
|
| 215 |
setSize(width = null, height = null) {
|
| 216 |
// By default it is going to cover the whole page and then we will
|
| 217 |
// cut out a chunk for the element to be visible out of it
|
|
|
|
| 219 |
this.overlay.height = height || this.window.innerHeight;
|
| 220 |
}
|
| 221 |
|
| 222 |
+
/**
|
| 223 |
+
* Refreshes the overlay i.e. sets the size according to current window size
|
| 224 |
+
* And moves the highlight around if necessary
|
| 225 |
+
*
|
| 226 |
+
* @param animate bool
|
| 227 |
+
*/
|
| 228 |
refresh(animate = true) {
|
| 229 |
this.setSize();
|
| 230 |
|
assets/scripts/src/position.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
| 4 |
*/
|
| 5 |
export default class Position {
|
| 6 |
/**
|
| 7 |
-
* @param left
|
| 8 |
-
* @param top
|
| 9 |
-
* @param right
|
| 10 |
-
* @param bottom
|
| 11 |
*/
|
| 12 |
constructor({
|
| 13 |
left = 0,
|
|
@@ -21,10 +21,19 @@ export default class Position {
|
|
| 21 |
this.bottom = bottom;
|
| 22 |
}
|
| 23 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
canHighlight() {
|
| 25 |
return this.left < this.right && this.top < this.bottom;
|
| 26 |
}
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
equals(position) {
|
| 29 |
return this.left.toFixed(3) === position.left.toFixed(3) &&
|
| 30 |
this.right.toFixed(3) === position.right.toFixed(3) &&
|
|
|
|
| 4 |
*/
|
| 5 |
export default class Position {
|
| 6 |
/**
|
| 7 |
+
* @param left number
|
| 8 |
+
* @param top number
|
| 9 |
+
* @param right number
|
| 10 |
+
* @param bottom number
|
| 11 |
*/
|
| 12 |
constructor({
|
| 13 |
left = 0,
|
|
|
|
| 21 |
this.bottom = bottom;
|
| 22 |
}
|
| 23 |
|
| 24 |
+
/**
|
| 25 |
+
* Checks if the position is valid to be highlighted
|
| 26 |
+
* @returns {boolean}
|
| 27 |
+
*/
|
| 28 |
canHighlight() {
|
| 29 |
return this.left < this.right && this.top < this.bottom;
|
| 30 |
}
|
| 31 |
|
| 32 |
+
/**
|
| 33 |
+
* Checks if the given position is equal to the passed position
|
| 34 |
+
* @param position Position
|
| 35 |
+
* @returns {boolean}
|
| 36 |
+
*/
|
| 37 |
equals(position) {
|
| 38 |
return this.left.toFixed(3) === position.left.toFixed(3) &&
|
| 39 |
this.right.toFixed(3) === position.right.toFixed(3) &&
|
assets/scripts/src/sholo.js
CHANGED
|
@@ -6,6 +6,11 @@ import './polyfill';
|
|
| 6 |
* Plugin class that drives the plugin
|
| 7 |
*/
|
| 8 |
export default class Sholo {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
constructor({
|
| 10 |
opacity = 0.75,
|
| 11 |
padding = 10,
|
|
@@ -28,30 +33,50 @@ export default class Sholo {
|
|
| 28 |
this.bind();
|
| 29 |
}
|
| 30 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
bind() {
|
| 32 |
-
// @todo: add throttling in all the listeners
|
| 33 |
this.document.addEventListener('scroll', this.onScroll, false);
|
| 34 |
this.document.addEventListener('DOMMouseScroll', this.onScroll, false);
|
| 35 |
this.window.addEventListener('resize', this.onResize, false);
|
| 36 |
this.window.addEventListener('keyup', this.onKeyUp, false);
|
| 37 |
}
|
| 38 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 39 |
onScroll() {
|
| 40 |
-
// Refresh without animation on scroll
|
| 41 |
this.overlay.refresh(false);
|
| 42 |
}
|
| 43 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
onResize() {
|
| 45 |
// Refresh with animation
|
| 46 |
this.overlay.refresh(true);
|
| 47 |
}
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
onKeyUp(event) {
|
| 50 |
if (event.keyCode === 27) {
|
| 51 |
this.overlay.clear();
|
| 52 |
}
|
| 53 |
}
|
| 54 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
highlight(selector) {
|
| 56 |
let domElement;
|
| 57 |
|
|
|
|
| 6 |
* Plugin class that drives the plugin
|
| 7 |
*/
|
| 8 |
export default class Sholo {
|
| 9 |
+
/**
|
| 10 |
+
* @param opacity number
|
| 11 |
+
* @param padding number
|
| 12 |
+
* @param animate boolean
|
| 13 |
+
*/
|
| 14 |
constructor({
|
| 15 |
opacity = 0.75,
|
| 16 |
padding = 10,
|
|
|
|
| 33 |
this.bind();
|
| 34 |
}
|
| 35 |
|
| 36 |
+
/**
|
| 37 |
+
* Binds any DOM events listeners
|
| 38 |
+
* @todo: add throttling in all the listeners
|
| 39 |
+
*/
|
| 40 |
bind() {
|
|
|
|
| 41 |
this.document.addEventListener('scroll', this.onScroll, false);
|
| 42 |
this.document.addEventListener('DOMMouseScroll', this.onScroll, false);
|
| 43 |
this.window.addEventListener('resize', this.onResize, false);
|
| 44 |
this.window.addEventListener('keyup', this.onKeyUp, false);
|
| 45 |
}
|
| 46 |
|
| 47 |
+
/**
|
| 48 |
+
* Handler for the onScroll event on document
|
| 49 |
+
* Refreshes without animation on scroll to make sure
|
| 50 |
+
* that the highlighted part travels with the scroll
|
| 51 |
+
*/
|
| 52 |
onScroll() {
|
|
|
|
| 53 |
this.overlay.refresh(false);
|
| 54 |
}
|
| 55 |
|
| 56 |
+
/**
|
| 57 |
+
* Handler for the onResize DOM event
|
| 58 |
+
* Refreshes with animation on scroll to make sure that
|
| 59 |
+
* the highlighted part travels with the width change of window
|
| 60 |
+
*/
|
| 61 |
onResize() {
|
| 62 |
// Refresh with animation
|
| 63 |
this.overlay.refresh(true);
|
| 64 |
}
|
| 65 |
|
| 66 |
+
/**
|
| 67 |
+
* Clears the overlay on escape key process
|
| 68 |
+
* @param event
|
| 69 |
+
*/
|
| 70 |
onKeyUp(event) {
|
| 71 |
if (event.keyCode === 27) {
|
| 72 |
this.overlay.clear();
|
| 73 |
}
|
| 74 |
}
|
| 75 |
|
| 76 |
+
/**
|
| 77 |
+
* Highlights the given selector
|
| 78 |
+
* @param selector
|
| 79 |
+
*/
|
| 80 |
highlight(selector) {
|
| 81 |
let domElement;
|
| 82 |
|
index.html
CHANGED
|
@@ -44,22 +44,8 @@
|
|
| 44 |
|
| 45 |
<script src="./assets/scripts/dist/sholo.js"></script>
|
| 46 |
<script>
|
| 47 |
-
const
|
| 48 |
-
|
| 49 |
-
'.section__how',
|
| 50 |
-
'.section__examples'
|
| 51 |
-
];
|
| 52 |
-
|
| 53 |
-
const sholo = new Sholo({
|
| 54 |
-
padding: 10,
|
| 55 |
-
animate: true
|
| 56 |
-
});
|
| 57 |
-
|
| 58 |
-
nodesToSelect.forEach((nodeToSelect, index) => {
|
| 59 |
-
window.setTimeout(() => {
|
| 60 |
-
sholo.highlight(nodeToSelect);
|
| 61 |
-
}, index * 1000);
|
| 62 |
-
});
|
| 63 |
</script>
|
| 64 |
</body>
|
| 65 |
</html>
|
|
|
|
| 44 |
|
| 45 |
<script src="./assets/scripts/dist/sholo.js"></script>
|
| 46 |
<script>
|
| 47 |
+
const sholo = new Sholo();
|
| 48 |
+
sholo.highlight('.section__header');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
</script>
|
| 50 |
</body>
|
| 51 |
</html>
|