PageSourceSearch

https://www.kelseaballerini.com/assets/a9c4a298/javascripts/motion.js

js kelseaballerini.com collected 2026-09-24 21:18:56 UTC 5,257 bytes, 158 lines download raw bytes

1/* USAGE
2<!-- STAGGER -->
3<div data-motion-id="hero" data-motion-stagger=".2">
4  <div class="" data-motion data-motion-trigger="hero" data-motion-stagger-group="hero" data-motion-start="top bottom" data-motion-toggle-actions="play none none none" data-motion-from='{"y": "100%", "opacity": "0"}'></div>
5  <div class="" data-motion data-motion-trigger="hero" data-motion-stagger-group="hero" data-motion-start="top bottom" data-motion-toggle-actions="play none none none" data-motion-from='{"x": "-100%", "scale": ".5"}'></div>
6</div>
7
8<!-- TRIGGER -->
9<div data-motion-id="about">
10  <div class="" data-motion data-motion-trigger="about" data-motion-start="top bottom" data-motion-end="bottom top" data-motion-from='{"yPecent": "100"}'></div>
11</div>
12
13<!-- SELF -->
14<div class="" data-motion data-motion-start="top bottom" data-motion-end="bottom top" data-motion-from='{"yPecent": "100"}'></div>
15*/
16
17import { gsap } from "https://cdn.jsdelivr.net/npm/[email protected]/index.js";
18import * as ScrollTriggerModule from 'https://cdn.jsdelivr.net/npm/[email protected]/ScrollTrigger.js';
19
20let breakpointUpTablet = 750,
21    breakpointUpDesktop = 990
22
23//Register plugin
24const ScrollTrigger = ScrollTriggerModule.ScrollTrigger || ScrollTriggerModule.default;
25gsap.registerPlugin(ScrollTrigger);
26
27//Define element
28const elem = document.querySelectorAll('[data-motion]')
29
30//Define animation
31const animation = (el) => {
32  let scrub = true,
33      ease = 'linear'
34  if (el.hasAttribute('data-motion-toggle-actions')) {
35    scrub = false
36    ease = 'power4.out'
37  }
38  if (el.hasAttribute('data-motion-ease')) {
39    ease = el.getAttribute('data-motion-ease')
40  }
41  const 
42  trigger = document.querySelector('[data-motion-id="'+el.getAttribute('data-motion-trigger')+'"]') || el,
43  endTrigger = document.querySelector('[data-motion-id="'+el.getAttribute('data-motion-trigger-end')+'"]') || trigger || el,
44  start = el.getAttribute('data-motion-start') || 'top bottom',
45  end = el.getAttribute('data-motion-end') || 'bottom top',
46  toggleActions = el.getAttribute('data-motion-toggle-actions') || 'none',
47  duration = el.getAttribute('data-motion-duration') || 1, 
48  delay = el.getAttribute('data-motion-delay') || 0, 
49  set = JSON.parse(el.getAttribute('data-motion-set')),
50  from = JSON.parse(el.getAttribute('data-motion-from')),
51  to = JSON.parse(el.getAttribute('data-motion-to')),
52  markers = el.getAttribute('data-motion-markers') || false,
53  tl = gsap.timeline({
54    scrollTrigger: {
55      trigger: trigger,
56      endTrigger: endTrigger,
57      start:  start,
58      end: end,
59      scrub: scrub,
60      markers: markers,
61      toggleActions: toggleActions,
62    },
63    defaults: {
64      ease: ease,
65      yoyoEase: true,
66      duration: duration,
67      delay: delay,
68      immediateRender: true
69    }
70  })
71  if (el.hasAttribute('data-motion-stagger-group')) {
72    let group = document.querySelectorAll('[data-motion-stagger-group="'+el.getAttribute('data-motion-stagger-group')+'"]'),
73    delay = parseFloat(document.querySelector('[data-motion-id="'+el.getAttribute('data-motion-stagger-group')+'"]').getAttribute('data-motion-stagger')) || .1
74    group.forEach((item, index) => {
75      if (index !== 0) {
76        let currentDelay = delay + ((index - 1) * delay)
77        item.setAttribute('data-motion-delay', currentDelay)
78      }
79    })
80  }
81  if (el.hasAttribute('data-motion-from')) {
82    tl.from(el, { ...from,
83      onComplete: () => gsap.set(el, {clearProps: "all"})
84    })
85  } else if (!el.hasAttribute('data-motion-from')) {
86    if (el.hasAttribute('data-motion-set')) {
87      tl.set(el, set)
88    }
89    tl.to(el, to)    
90  }
91}
92
93//Define breakpoint check
94const breakpointCheck = (el) => {
95  if (el.hasAttribute('data-motion-breakpoint')) {
96    const mediaQuery = gsap.matchMedia()
97    let breakpoint = null
98  
99    if (el.getAttribute('data-motion-breakpoint') === 'tablet') { breakpoint = breakpointUpTablet }
100    if (el.getAttribute('data-motion-breakpoint') === 'desktop') { breakpoint = breakpointUpDesktop }
101  
102    mediaQuery.add("(min-width: " + (breakpoint) + "px)", () => {
103      animation(el)
104    })
105  } else {
106    animation(el)
107  }
108}
109
110//FOUC Fix for teaser
111elem.forEach(elem => {
112  if (elem.hasAttribute('data-motion-toggle-actions')) {
113    gsap.set(elem, {
114      autoAlpha: 0
115    })
116  }
117})
118
119//If element is scrub
120export const scrub = () => {
121  if (typeof (elem) != 'undefined' && elem != null) {
122    elem.forEach(elem => {
123      if (!elem.hasAttribute('data-motion-toggle-actions')) {
124        breakpointCheck(elem)
125      }
126    })
127  }
128}
129
130//If element is toggle actions
131export const teaserIn = () => {
132  if (typeof (elem) != 'undefined' && elem != null) {
133    elem.forEach(elem => {
134      if (elem.hasAttribute('data-motion-toggle-actions')) {
135        //Reverse FOUC fix
136        gsap.set(elem, {
137          autoAlpha: 1
138        })
139        breakpointCheck(elem)
140      }
141    })
142  }
143}
144
145//Page unload
146export const teaserOut = () => {
147  if (typeof (elem) != 'undefined' && elem != null) {
148    const tl = gsap.timeline()
149    tl.to(elem, {
150      scale: 0
151    })
152    return tl
153  }
154}
155
156scrub()
157teaserIn()
158// teaserOut()

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.