rytm-webflow 2.1.1 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -265,7 +265,19 @@ Animate elements nested under the WebflowView container when scrolled into viewp
|
|
|
265
265
|
### Scrollmagic - animate elements when scrolled into viewport
|
|
266
266
|
Scroll-triggered-animations of any element inside the *WebflowView* container. Use the `webscroll` data attributes (initial, show, hide):
|
|
267
267
|
```html
|
|
268
|
-
<div data-webscroll-initial="
|
|
268
|
+
<div data-webscroll-initial="o:0" data-webscroll-show="o:1,t:.5" data-webscroll-hide="o:0,t:.3">
|
|
269
|
+
...
|
|
270
|
+
</div>
|
|
271
|
+
```
|
|
272
|
+
Use the `webset` data attribute to pass some additional parameters, eg. the trigger element. This can be helpful when animating any element in the Y axis, eg:
|
|
273
|
+
```html
|
|
274
|
+
<div data-webset="trigger:parent" data-webscroll-initial="y:100" data-webscroll-show="y:0,t:.5,e:power3.out" data-webscroll-hide="o:0,t:.4">
|
|
275
|
+
...
|
|
276
|
+
</div>
|
|
277
|
+
```
|
|
278
|
+
By default scroll-troggered animations are only fired once. You can change this by setting the `fireOnce` parameter to `false`, example:
|
|
279
|
+
```html
|
|
280
|
+
<div data-webset="fireOnce:false" data-webscroll-initial="o:0" data-webscroll-show="o:1,t:.5">
|
|
269
281
|
...
|
|
270
282
|
</div>
|
|
271
283
|
```
|
package/package.json
CHANGED
package/scripts/aswap/ASwap.js
CHANGED
|
@@ -33,6 +33,7 @@ class ASwap {
|
|
|
33
33
|
onRequestUrl: () => {},
|
|
34
34
|
onRequestLoad: () => {},
|
|
35
35
|
onRequestLoaded: () => {},
|
|
36
|
+
onRequestSameUrl: () => {},
|
|
36
37
|
onViewHide: () => {},
|
|
37
38
|
onViewHidden: () => {},
|
|
38
39
|
onViewSwapStart: () => {},
|
|
@@ -63,6 +64,7 @@ class ASwap {
|
|
|
63
64
|
this.dispatcher.on(Events.NAV_REQUEST_URL, this.onRequestUrl.bind(this));
|
|
64
65
|
this.dispatcher.on(Events.NAV_REQUEST_LOAD, this.onRequestLoad.bind(this));
|
|
65
66
|
this.dispatcher.on(Events.NAV_REQUEST_LOADED, this.onRequestLoaded.bind(this));
|
|
67
|
+
this.dispatcher.on(Events.NAV_REQUEST_SAME_URL, this.onRequestSameUrl.bind(this));
|
|
66
68
|
this.dispatcher.on(Events.NAV_VIEW_HIDE, this.onViewHide.bind(this));
|
|
67
69
|
this.dispatcher.on(Events.NAV_VIEW_HIDDEN, this.onViewHidden.bind(this));
|
|
68
70
|
this.dispatcher.on(Events.NAV_SWAP_START, this.onViewSwapStart.bind(this));
|
|
@@ -82,7 +84,7 @@ class ASwap {
|
|
|
82
84
|
**/
|
|
83
85
|
openURL(url, noHistory = false, useCache = true) {
|
|
84
86
|
if (this.dispatcher) {
|
|
85
|
-
this.dispatcher.openURL(url, noHistory, useCache)
|
|
87
|
+
this.dispatcher.openURL(url, noHistory, useCache);
|
|
86
88
|
}
|
|
87
89
|
}
|
|
88
90
|
|
|
@@ -91,7 +93,7 @@ class ASwap {
|
|
|
91
93
|
this.getActiveControlles().forEach( (c, index)=> {
|
|
92
94
|
c.onRequestUrl(e);
|
|
93
95
|
});
|
|
94
|
-
this.events.onRequestUrl()
|
|
96
|
+
this.events.onRequestUrl();
|
|
95
97
|
}
|
|
96
98
|
onRequestLoad(e) {
|
|
97
99
|
document.documentElement.classList.add('js');
|
|
@@ -99,14 +101,17 @@ class ASwap {
|
|
|
99
101
|
this.getActiveControlles().forEach( (c, index)=> {
|
|
100
102
|
c.onRequestLoad(e);
|
|
101
103
|
})
|
|
102
|
-
this.events.onRequestLoad()
|
|
104
|
+
this.events.onRequestLoad();
|
|
103
105
|
}
|
|
104
106
|
onRequestLoaded(e) {
|
|
105
107
|
this.getControllersFromContainer(e.target.freshContent).forEach( (c, index)=> {
|
|
106
108
|
c.onRequestLoaded(e);
|
|
107
109
|
});
|
|
108
110
|
document.documentElement.classList.remove("as-request-loading");
|
|
109
|
-
this.events.onRequestLoaded()
|
|
111
|
+
this.events.onRequestLoaded();
|
|
112
|
+
}
|
|
113
|
+
onRequestSameUrl(e) {
|
|
114
|
+
this.events.onRequestSameUrl();
|
|
110
115
|
}
|
|
111
116
|
onViewHide(e) {
|
|
112
117
|
document.documentElement.classList.add('as-hide');
|
|
@@ -116,7 +121,7 @@ class ASwap {
|
|
|
116
121
|
c.onViewHide(e);
|
|
117
122
|
}
|
|
118
123
|
});
|
|
119
|
-
this.events.onViewHide()
|
|
124
|
+
this.events.onViewHide();
|
|
120
125
|
}
|
|
121
126
|
onViewHidden(e) {
|
|
122
127
|
document.documentElement.classList.remove('as-hide');
|
|
@@ -126,26 +131,26 @@ class ASwap {
|
|
|
126
131
|
c.onViewHidden(e);
|
|
127
132
|
}
|
|
128
133
|
});
|
|
129
|
-
this.events.onViewHidden()
|
|
134
|
+
this.events.onViewHidden();
|
|
130
135
|
}
|
|
131
136
|
onViewSwapStart(e) {
|
|
132
137
|
this.getControllersFromContainer(e.target.freshContent).forEach( (c, index)=> {
|
|
133
138
|
c.onViewSwapStart(e);
|
|
134
139
|
});
|
|
135
|
-
this.events.onViewSwapStart()
|
|
140
|
+
this.events.onViewSwapStart();
|
|
136
141
|
}
|
|
137
142
|
onViewSwapComplete(e) {
|
|
138
143
|
this.getControllersFromContainer(e.target.freshContent).forEach( (c, index)=> {
|
|
139
144
|
c.onViewSwapComplete(e);
|
|
140
145
|
});
|
|
141
|
-
this.events.onViewSwapComplete()
|
|
146
|
+
this.events.onViewSwapComplete();
|
|
142
147
|
}
|
|
143
148
|
onViewShow(e) {
|
|
144
149
|
document.documentElement.classList.add('as-show');
|
|
145
150
|
this.getControllersFromContainer(e.target.freshContent).forEach( (c, index)=> {
|
|
146
151
|
c.onViewShow(e);
|
|
147
152
|
});
|
|
148
|
-
this.events.onViewShow()
|
|
153
|
+
this.events.onViewShow();
|
|
149
154
|
}
|
|
150
155
|
onViewShown(e) {
|
|
151
156
|
document.documentElement.classList.add('as-show');
|
|
@@ -310,6 +310,7 @@ class ASwapDispatcher extends EventDispatcher {
|
|
|
310
310
|
// check if url changed
|
|
311
311
|
if (url == this.getCurrentUrl()) {
|
|
312
312
|
this.trace("url didn't change", url);
|
|
313
|
+
this.dispatch(Events.NAV_REQUEST_SAME_URL);
|
|
313
314
|
if (this.refreshOnSameUrl) {
|
|
314
315
|
window.location.href = url;
|
|
315
316
|
}
|
package/scripts/aswap/Events.js
CHANGED
|
@@ -3,6 +3,7 @@ const Events = {
|
|
|
3
3
|
NAV_REQUEST_URL: "nav_open_url",
|
|
4
4
|
NAV_REQUEST_LOAD: "nav_request_load",
|
|
5
5
|
NAV_REQUEST_LOADED: "nav_request_loaded",
|
|
6
|
+
NAV_REQUEST_SAME_URL: "nav_same_url",
|
|
6
7
|
|
|
7
8
|
// * animation related events: hide / hidden / show / shown
|
|
8
9
|
NAV_VIEW_HIDE: "nav_veiw_hide",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import gsap from 'gsap';
|
|
2
2
|
import View from './View';
|
|
3
3
|
import { getWebflowAnimationProps, parseProps } from './../lib/dataTweenParser';
|
|
4
|
+
import { CLASS_NAME_WEBSCROLL_FIRED } from './WebflowView';
|
|
4
5
|
|
|
5
6
|
// data-webscroll-... (scroll magic)
|
|
6
7
|
const DATA_ATTR_WEBSCROLL_INIT = "webscroll-initial";
|
|
@@ -49,6 +50,8 @@ class WebflowListView extends View {
|
|
|
49
50
|
}
|
|
50
51
|
// show web scroll element
|
|
51
52
|
webScrollElementShow(el, delay) {
|
|
53
|
+
// check if element is in viewport
|
|
54
|
+
if (!this.isElementInViewport(el)) return;
|
|
52
55
|
const propsInitial = this.getTweenProps(el, DATA_ATTR_WEBSCROLL_INIT);
|
|
53
56
|
const propsShow = this.getTweenProps(el, DATA_ATTR_WEBSCROLL_SHOW);
|
|
54
57
|
if (propsInitial && propsShow) {
|
|
@@ -56,6 +59,7 @@ class WebflowListView extends View {
|
|
|
56
59
|
gsap.killTweensOf(el);
|
|
57
60
|
gsap.set(el, {...propsInitial.tween});
|
|
58
61
|
gsap.to(el, {duration: propsShow.time, ...propsShow.tween, delay});
|
|
62
|
+
el.classList.add(CLASS_NAME_WEBSCROLL_FIRED);
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
/**
|
|
@@ -72,6 +76,16 @@ class WebflowListView extends View {
|
|
|
72
76
|
getDataAttributeName(name) {
|
|
73
77
|
return name.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); });
|
|
74
78
|
}
|
|
79
|
+
// is element (any part of element) visible in scrolled viewport
|
|
80
|
+
isElementInViewport(el) {
|
|
81
|
+
const rect = el.getBoundingClientRect();
|
|
82
|
+
const scrollY = window.scrollY;
|
|
83
|
+
// element position
|
|
84
|
+
const elTop = rect.top + scrollY;
|
|
85
|
+
const elBottom = elTop + rect.height;
|
|
86
|
+
// check if element is in viewport
|
|
87
|
+
return (elTop < (scrollY + window.innerHeight) && elBottom >= scrollY);
|
|
88
|
+
}
|
|
75
89
|
|
|
76
90
|
}
|
|
77
91
|
export default WebflowListView
|
|
@@ -18,6 +18,9 @@ const DATA_ATTR_STAGGER_INIT = "stagger-initial";
|
|
|
18
18
|
const DATA_ATTR_STAGGER_SHOW = "stagger-show";
|
|
19
19
|
const DATA_ATTR_STAGGER_HIDE = "stagger-hide";
|
|
20
20
|
const DATA_ATTR_SETUP = "webset";
|
|
21
|
+
const PROP_KEY_WEBSCROLL_FIRE_ONCE = "fireOnce";
|
|
22
|
+
|
|
23
|
+
export const CLASS_NAME_WEBSCROLL_FIRED = "webflow-scroll-fired";
|
|
21
24
|
|
|
22
25
|
class WebflowView extends View {
|
|
23
26
|
|
|
@@ -35,8 +38,9 @@ class WebflowView extends View {
|
|
|
35
38
|
* animate in (show)
|
|
36
39
|
**/
|
|
37
40
|
show(container) {
|
|
38
|
-
super.show(container);
|
|
39
41
|
this.container = container;
|
|
42
|
+
this.hideScrollElements();
|
|
43
|
+
super.show(container);
|
|
40
44
|
// show Aswap webviews
|
|
41
45
|
this.webViewsShow();
|
|
42
46
|
// show stagger elements
|
|
@@ -154,6 +158,22 @@ class WebflowView extends View {
|
|
|
154
158
|
}
|
|
155
159
|
}
|
|
156
160
|
// ### ScrollMagic ###
|
|
161
|
+
// hide scenes (before show animation)
|
|
162
|
+
hideScrollElements() {
|
|
163
|
+
if (!this.container) {
|
|
164
|
+
console.warn("Unknown container", this);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
const list = [...this.container.querySelectorAll('*[data-' + DATA_ATTR_WEBSCROLL_SHOW + ']')];
|
|
168
|
+
list.forEach(this.hideScrollElement.bind(this));
|
|
169
|
+
}
|
|
170
|
+
hideScrollElement(el, index) {
|
|
171
|
+
const propsInitial = this.getTweenProps(el, DATA_ATTR_WEBSCROLL_INIT);
|
|
172
|
+
if (propsInitial) {
|
|
173
|
+
gsap.killTweensOf(el);
|
|
174
|
+
gsap.set(el, {...propsInitial.tween});
|
|
175
|
+
}
|
|
176
|
+
}
|
|
157
177
|
/**
|
|
158
178
|
* Build scenes for scrollmagic
|
|
159
179
|
*/
|
|
@@ -174,14 +194,19 @@ class WebflowView extends View {
|
|
|
174
194
|
const propsInitial = this.getTweenProps(el, DATA_ATTR_WEBSCROLL_INIT);
|
|
175
195
|
const propsShow = this.getTweenProps(el, DATA_ATTR_WEBSCROLL_SHOW);
|
|
176
196
|
const setup = parseProps(el.dataset[DATA_ATTR_SETUP]);
|
|
197
|
+
const fireOnce = setup[PROP_KEY_WEBSCROLL_FIRE_ONCE] === "false" ? false : true;
|
|
177
198
|
if (propsInitial && propsShow) {
|
|
178
199
|
const smsp = getScrollMagicSceneProps(el, setup);
|
|
179
200
|
const scene = new ScrollMagic.Scene(smsp);
|
|
180
201
|
scene.on("start", (e) => {
|
|
202
|
+
if (fireOnce && el.classList.contains(CLASS_NAME_WEBSCROLL_FIRED)) {
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
181
205
|
if (e.scrollDirection === "FORWARD") {
|
|
182
206
|
gsap.killTweensOf(el);
|
|
183
207
|
gsap.set(el, {...propsInitial.tween});
|
|
184
208
|
gsap.to(el, {duration: propsShow.time, ...propsShow.tween});
|
|
209
|
+
el.classList.add(CLASS_NAME_WEBSCROLL_FIRED);
|
|
185
210
|
}
|
|
186
211
|
});
|
|
187
212
|
scene.addTo(scrollController.get());
|