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