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="y:100" data-webscroll-show="y:0,t:.5" data-webscroll-hide="o:0,t:.4">
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rytm-webflow",
3
- "version": "2.1.1",
3
+ "version": "2.1.3",
4
4
  "description": "rytm webflow pack - ASwap, ShowUp",
5
5
  "main": "scripts/index.js",
6
6
  "scripts": {
@@ -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
  }
@@ -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());