hendrikeng
Members-
Posts
17 -
Joined
-
Last visited
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
hendrikeng's Achievements
5
Reputation
-
Thanks a lot @mikel, i guess i might have overcomplicated things , i managed to get it working. I basically wanted to avoid doubling the code for the touch events, anyways it works so far. Thanks a again for the help const who = { trigger: [...document.getElementsByClassName('slide')], init: () => { console.log('init'); who.trigger.forEach.call(who.trigger, (el) => { el.addEventListener('mouseover', who.animateOver, false); el.addEventListener('touchstart', who.animateOver, false); }); who.trigger.forEach.call(who.trigger, (el) => { el.addEventListener('mouseout', who.animateOut, false); el.addEventListener('touchend', who.animateOut, false); }); }, animateOver() { const image = this.getElementsByClassName('image'); const heading = this.getElementsByClassName('text1'); const subheading = this.getElementsByClassName('text2'); // animate image TweenMax.to(image, 0.25, { yPercent: 35, ease: Power1.easeOut, }); // animate heading TweenMax.to(heading, 0.75, { yPercent: -180, ease: Power1.easeOut, }); // animate subheading TweenMax.to(subheading, 0.75, { yPercent: -90, ease: Power1.easeOut, }); }, animateOut() { const image = this.getElementsByClassName('image'); const heading = this.getElementsByClassName('text1'); const subheading = this.getElementsByClassName('text2'); // animate image TweenMax.to(image, 0.75, { yPercent: 0, ease: Bounce.easeOut, }); // animate heading TweenMax.to(heading, 0.75, { yPercent: 0, ease: Bounce.easeOut, }); // animate subheading TweenMax.to(subheading, 0.75, { yPercent: 0, ease: Bounce.easeOut, }); }, }; who.init();
-
I tried to extend my code but run into a new issue. i am trying to understand how i would pass an argument to a function inside a forEach.call. I basically converted my code into an object literal and split up the functions to be more dry when i would later add more animations. The problem is, that it logs the element on load but not anymore after that, i guess its because the variable doesn't exist after the first log anymore. how would i make it work, or is the approach completely wrong and nonsense? thanks for all the help. const who = { trigger: [...document.getElementsByClassName('slide')], init: () => { console.log('init'); who.trigger.forEach.call(who.trigger, (el) => { el.addEventListener('mouseover', who.animateOver(el), false); }); who.trigger.forEach.call(who.trigger, (el) => { el.addEventListener('mouseout', who.animateOut(el), false); }); }, animateOver: (el) => { // animate image const image = el.getElementsByClassName("img")[0]; TweenMax.to(image, 0.25, { yPercent: 35, ease: Power1.easeOut, }); // animate text const text = el.getElementsByClassName("text")[0]; TweenMax.to(text, 0.25, { yPercent: 35, ease: Power1.easeOut, }); }, animateOut: (el) => { // animate image const image = el.getElementsByClassName('img')[0]; TweenMax.to(image, 0.75, { yPercent: 0, ease: Bounce.easeOut, }); // animate something different const text = el.getElementsByClassName('text')[0]; TweenMax.to(text, 0.75, { yPercent: 0, ease: Bounce.easeOut, }); }, debug: () => { console.log('debug'); }, destroy() { console.log('destroy'); }, }; who.init(); It does work if i don't pass an argument but the problem here is that it just triggers the events target and will result in stuttering and not being able to choose the actual trigger (i want to have both triggered when hovering the image and not on hovering text or image) if that makes sense this is the example: https://codepen.io/HendrikEng/pen/ypqMNP?editors=1111 const who = { trigger: [...document.getElementsByClassName('slide')], init: () => { console.log('init'); who.trigger.forEach.call(who.trigger, (el) => { el.addEventListener('mouseover', who.animateOver, false); }); who.trigger.forEach.call(who.trigger, (el) => { el.addEventListener('mouseout', who.animateOut, false); }); }, animateOver: (el) => { // animate image const image = el.target; TweenMax.to(image, 0.25, { yPercent: 35, ease: Power1.easeOut, }); // animate text /* const text = el.target; TweenMax.to(text, 0.25, { css: { opacity: '0', }, ease: Power1.easeOut, }); */ }, animateOut: (el) => { // animate image const image = el.target; TweenMax.to(image, 0.75, { yPercent: 0, ease: Bounce.easeOut, }); // animate Text /* const text = el.target; TweenMax.to(text, 0.75, { css: { opacity: '0', }, }); */ }, debug: () => { console.log('debug'); }, destroy() { console.log('destroy'); }, }; onload = () => who.init();
-
Thanks a lot @mikel that really helped! If anyone needs the jQuery free version of mikels pen : TweenLite.set(".page", { autoAlpha: 1, xPercent: -100 }); const page = document.querySelectorAll(".page"); const button = document.querySelectorAll(".button"); button.forEach.call(button, function(el) { el.addEventListener("mouseover", function(e) { let thisPage = this.getAttribute("id"); TweenMax.to(page, 0.2, { xPercent: -100, ease: Sine.easeInOut, onComplete: newImage }); function newImage() { TweenMax.to(thisPage, 0.8, { delay: 0.4, xPercent: 0, ease: Sine.easeInOut }); } }); }); button.forEach.call(button, function(el) { el.addEventListener("mouseout", function(e) { let thisPage = this.getAttribute("id"); console.log(thisPage); TweenMax.to(page, 0.4, { xPercent: -100, ease: Power2.easeIn }); }); }); thanks again
-
Hey there, happy new year first of all I am a bit confused with an animation i tried to achieve... i basically want to have each image separately animated and not all of them together...i tried to loop over all elements but its still animating all images together...would i need a timeline or is the approach completely wrong? const who = { trigger: [...document.querySelectorAll(".slide")], image: [...document.querySelectorAll(".slide img")], init: () => { who.trigger.forEach(element => { element.addEventListener("mouseover", who.animateOnMouseEnter); element.addEventListener("mouseout", who.animateOnMouseOut); }); }, animateOnMouseEnter: () => { console.log("animateOnMouseEnter"); who.image.forEach(element => { TweenMax.to(element, 0.25, { y: 35, ease: Power1.easeOut, repeat: 0 }); }); }, animateOnMouseOut: () => { console.log(" animateOnMouseOut"); who.image.forEach(element => { TweenMax.to(element, 0.75, { y: 0, ease: Bounce.easeOut, repeat: 0 }); }); }, debug: () => { // }, destroy() { // } }; who.init();
-
Thanks Jack, i guess it would have been way better to just do it from the start if you resize the window..it should fire the animation if the logo touches the colored area, if you resize it and the logo is in the white area, the tweens should have reseted to their initial color. Anyway, i just figured while making the codepen that it is indeed scrollmagic related...the tweens do reset fine, its just the scrollmagic controller that keeps firing the tweens
-
Thanks for the patience i guess its a bit hard to understand what i am trying to achieve. I basically have a logo that needs to change its color on mobile devices if the user scrolls over a section that has the same color as the logo. I managed to get it working, the only problem was, that the logo won't change it's color back to normal if e.g. the user changes the viewport from mobile to desktop. The second animation is just a staggerFromTo that only happens on desktop devices, since its a timeline it also worked as u described. The animation resets once u change the viewport to mobile and restarts if its back to desktop again....thats all fine. So its basically only the mobile animation, and i was already unsure if it's possible to use a timeline instead of Tweenmax for every change of the logo. The tweens just change the inner and outer logo fills once it touches a section that has the same background. Scrollmagic isn't doing much, its only triggering the tweens. I am not sure if it helps but i will post the index.js where i call the functions and the animation.js where they sit. I am already super thankful for all the help So i i felt already bad to bother you guys all the time ...you rock index.js: (enquire fires as soon as a breakpoint matches or unmatches) /** * Animations */ // Mobile Animationen enquire.register(breakpoint.forPhoneOnly, { match() { import('animation') .then((animation) => { animation.mobile.changeLogo.init(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, unmatch() { import('animation') .then((animation) => { // destroy mobile scrollMagic controller and reset scenes animation.mobile.controller.destroy(true); // clear and reset animations on tweens animation.mobile.changeLogo.destroyTweens(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, }); // Desktop Animationen enquire.register(breakpoint.forTabletPortraitUp, { match() { import('animation') .then((animation) => { animation.desktop.showcase.init(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, unmatch() { import('animation') .then((animation) => { // destroy desktop scrollMagic controller and reset scenes animation.desktop.controller.destroy(true); // clear and reset animations on tweens animation.desktop.showcase.destroyTweens(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, }); animation.js import ScrollMagic from 'scrollmagic'; import 'animation.gsap'; import TweenMax from 'TweenMax'; import TimelineLite from 'TimelineLite'; import 'EasePack'; /* eslint-disable no-unused-vars, no-undef, no-console */ /** * Mobile animations */ export const mobile = { controller: new ScrollMagic.Controller(), changeLogo: { init: () => { const tweens = { enterOuter: () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }, enterInner: () => { TweenMax.fromTo('.c-logo__inner', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }, leaveOuter: () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }, leaveInner: () => { TweenMax.fromTo('.c-logo__inner', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }, }; const trigger = document.querySelectorAll('.js-change-logo'); trigger.forEach((id) => { const scene = new ScrollMagic.Scene({ triggerElement: id, reverse: true, triggerHook: 0.065, duration: id.clientHeight, }) .on('enter', () => { tweens.enterOuter(); tweens.enterInner(); }) .on('leave', () => { tweens.leaveOuter(); tweens.leaveInner(); }) .addTo(mobile.controller); }); }, destroyTweens: () => { TweenMax.killTweensOf('.c-logo__outer'); TweenMax.killTweensOf('.c-logo__inner'); TweenMax.set('.c-logo__outer', { clearProps: 'all' }); TweenMax.set('.c-logo__inner', { clearProps: 'all' }); }, }, }; export const desktop = { controller: new ScrollMagic.Controller(), timeLineLite: new TimelineLite(), showcase: { init: () => { desktop.timeLineLite.staggerFromTo('.c-showcase-item', 0.3, { autoAlpha: 0, scale: 0, y: 0 }, { ease: Power4.easeOut, autoAlpha: 1, scale: 1, y: 0 }, 0.2); const scene = new ScrollMagic.Scene({ triggerElement: '.c-showcase', reverse: false, triggerHook: 0.5, }) .setTween(desktop.timeLineLite) .addTo(desktop.controller); }, destroyTweens: () => { desktop.timeLineLite.clear(); desktop.timeLineLite.set('.c-showcase-item', { clearProps: 'all' }); }, }, };
-
I got it working in an object literal, this way i am able to simply initialize the mobile animations and destroy them at specific breakpoints or similar. the only thing that i encountered is that the tweens won't reset and work again if i killed them. On a timeline i used 'timeLineLite.clear();' but since its not a timeline and i have to kill/clear all i did use TweenMax.killTweensOf .... i couldnt find anything like clearTweensOf.... or could i somehow wrap the different tweens in a timeline as well? Thanks for all the help and patience export const mobile = { controller: new ScrollMagic.Controller(), changeLogo: { init: () => { const tweens = { enterOuter: () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }, enterInner: () => { TweenMax.fromTo('.c-logo__inner', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }, leaveOuter: () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }, leaveInner: () => { TweenMax.fromTo('.c-logo__inner', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }, }; const trigger = document.querySelectorAll('.js-change-logo'); trigger.forEach((id) => { const scene = new ScrollMagic.Scene({ triggerElement: id, reverse: true, triggerHook: 0.065, duration: id.clientHeight, }) .on('enter', () => { tweens.enterOuter(); tweens.enterInner(); }) .on('leave', () => { tweens.leaveOuter(); tweens.leaveInner(); }) .addTo(mobile.controller); }); }, destroyTweens: () => { TweenMax.killTweensOf('.c-logo__outer'); TweenMax.killTweensOf('.c-logo__inner'); TweenMax.set('.c-logo__outer', { clearProps: 'all' }); TweenMax.set('.c-logo__inner', { clearProps: 'all' }); }, }, };
-
thanks a lot for the input and the videos carl and jack. it helped and i got a bit further but i still struggle to access specific methods from outside, but i think thats more an issue of my knowledge. i will try to dive deeper and get back when i made some progress. thanks
-
Thanks a lot Jack, its not necessary to create a new tween for each animation, i wasn't actually sure if its possible to use just the same and alter the animation? I also want to kill all the tweens it was just an example of what i tried...so would it be better to refactor the code then and just use one tween?
-
I kinda stumbled on a similar issue, in my animation.js i have the following tweens : export const tweenChangeLogo = { enterOuter: () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }, enterInner: () => { TweenMax.fromTo('.c-logo__inner', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }, leaveOuter: () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }, leaveInner: () => { TweenMax.fromTo('.c-logo__inner', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }, }; const changeLogoTrigger = document.querySelectorAll('.js-change-logo'); export function changeLogo() { changeLogoTrigger.forEach((trigger) => { const sceneChangeLogo = new ScrollMagic.Scene({ triggerElement: trigger, reverse: true, triggerHook: 0.065, duration: trigger.clientHeight, }) .on('enter', () => { tweenChangeLogo.enterOuter(); tweenChangeLogo.enterInner(); }) .on('leave', () => { tweenChangeLogo.leaveOuter(); tweenChangeLogo.leaveInner(); }) .addTo(controllerMobile); }); } since i stored the tweens in an object (to be able to export them and kill them in my index.js if needed) i tried to kill them via : (animation.tweenChangeLogo.enterOuter()).kill(); but its not working... is it even possible or the right way to store the tweeens in an object? thanks a lot once again
-
Thanks a lot Carl, if figured there is a way more simple way...in case anyone is looking for a similar effect: const changeLogoTrigger = document.querySelectorAll('.js-change-logo'); export function changeLogo() { changeLogoTrigger.forEach((trigger) => { const sceneChangeLogo = new ScrollMagic.Scene({ triggerElement: trigger, reverse: true, triggerHook: 0.065, duration: trigger.clientHeight, }) .on('enter', () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#4dabfc' }, { fill: '#fff' }); TweenMax.fromTo('.c-logo__inner', 1, { fill: '#fff' }, { fill: '#4dabfc' }); }) .on('leave', () => { TweenMax.fromTo('.c-logo__outer', 1, { fill: '#fff' }, { fill: '#4dabfc' }); TweenMax.fromTo('.c-logo__inner', 1, { fill: '#4dabfc' }, { fill: '#fff' }); }) // .addIndicators() .addTo(controllerMobile); }); }
- 2 replies
-
- gsap
- scrollmagic
-
(and 2 more)
Tagged with:
-
Hey there, i am trying to reverse/change the color of a logo based on the section its in. I got it working so far but i am kinda wondering if its the right and most performant approach (i kinda guess it isn't) I basically wont to use it on different subpages and the number of sections is variable. Thanks a lot, much appreciated const controllerMobile = new ScrollMagic.Controller(); const innerStart = new TimelineLite(); const innerEnd = new TimelineLite(); const outerStart = new TimelineLite(); const outerEnd = new TimelineLite(); innerStart.to('.js-logo__inner', 0.1, { fill: 'pink' }); innerEnd.to('.js-logo__inner', 0.1, { fill: 'orange' }); outerStart.to('.js-logo__outer', 0.1, { fill: 'orange' }); outerEnd.to('.js-logo__outer', 0.1, { fill: 'pink' }); const changeLogoStartTrigger = document.querySelectorAll('.js-change-logo--start'); const changeLogoEndTrigger = document.querySelectorAll('.js-change-logo--end'); function changeLogoStart() { changeLogoStartTrigger.forEach((triggerStart) => { const sceneChangeLogoStart = new ScrollMagic.Scene({ triggerElement: triggerStart, reverse: true, triggerHook: 0.065, offset: 0, }) .setTween(innerStart) .setTween(outerStart) .addIndicators() .addTo(controllerMobile); }); }; function changeLogoEnd() { changeLogoEndTrigger.forEach((triggerEnd) => { const sceneChangeLogoEnd = new ScrollMagic.Scene({ triggerElement: triggerEnd, reverse: true, triggerHook: 0.015, offset: 0, }) .setTween(innerEnd) .setTween(outerEnd) .addIndicators() .addTo(controllerMobile); }); }; changeLogoStart(); changeLogoEnd();
- 2 replies
-
- gsap
- scrollmagic
-
(and 2 more)
Tagged with:
-
Of course i tried it the bad way ...thanks for the heads up
-
Thanks a lot Jack, using TimlineLite or Max throwed TimelineLite __default.a.staggerFromTo is not a function but this worked like a charm animation.tweenShowcaseDesktop.forEach((id) => { id.kill(); }); thanks for such a quick reply, much appreciated!
-
Hey there, i tried to set up a Codepen, but unfortunately i couldn't get it work ....i am basically using webpack and es6 promises as well as enqurie.js and scrollmagic with gsap to trigger different tweens/scenes and kill them when the breakpoint is changed, unfortunately i get a animation.tweenShowcaseDesktop.kill is not a function on a specific tween. Since i am not able to make it work in codepen here is the module where i trigger the tweens and scrollmagic : I know its a very long snippet and shot , but maybe someone will spot my mistake right away. thanks a lot guys and keep up the awesome work. animation.js import ScrollMagic from 'scrollmagic'; import 'animation.gsap'; import 'debug.addIndicators'; import TweenMax from 'TweenMax'; import 'EasePack'; // eslint-disable-line /* eslint-disable no-unused-vars, no-undef */ /** * ***************************************************************************** * Mobile */ export const controllerMobile = new ScrollMagic.Controller(); /** * Service Tiles Mobile */ export function triggerServiceMobile() { const serviceTileFigure = document.getElementsByClassName( 'js-service-tile__fig', ); for (let i = 0; i < serviceTileFigure.length; i += 1) { const sceneServiceMobile = new ScrollMagic.Scene({ triggerElement: serviceTileFigure[i], reverse: true, triggerHook: 1, offset: 0, duration: 280, }) .on('start', () => { serviceTileFigure[i].classList.add('js-service-tile__fig--is-active'); }) .on('end', () => { serviceTileFigure[i].classList.remove( 'js-service-tile__fig--is-active', ); }) // .addIndicators() .addTo(controllerMobile); } } /** * ***************************************************************************** * Desktop */ export const controllerDesktop = new ScrollMagic.Controller(); /** * Service Desktop */ export const tweenServiceDesktop = TweenMax.fromTo( '.c-service', 1, { autoAlpha: 0, scale: 1, y: 200 }, { ease: Power0.easeIn, autoAlpha: 1, scale: 1, y: 0 }, ); export function triggerServiceDesktop() { // const sections = document.getElementsByTagName('section'); const sceneServiceDesktop = new ScrollMagic.Scene({ triggerElement: '#trigger', reverse: false, triggerHook: 0.75, }) // .addIndicators() .setTween(tweenServiceDesktop) .addTo(controllerDesktop); } /** * Portfolio Desktop */ export const tweenShowcaseDesktop = TweenMax.staggerFromTo( '.c-showcase-item', 0.4, { autoAlpha: 0, scale: 0, y: 0 }, { ease: Power4.easeOut, autoAlpha: 1, scale: 1, y: 0 }, 0.3, ); export function triggerShowcaseDesktop() { const showcaseTiles = document.getElementsByClassName('c-showcase-item'); const sceneShowcaseDesktop = new ScrollMagic.Scene({ triggerElement: '.c-showcase', reverse: false, triggerHook: 0.5, }) // .addIndicators() .setTween(tweenShowcaseDesktop) .addTo(controllerDesktop); } and my entry where i import and trigger them: // Mobile Animationen enquire.register(breakpoint.forPhoneOnly, { match() { import('changeLogoColor') .then((changeLogoColor) => { changeLogoColor.default(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); import('animation') .then((animation) => { animation.triggerServiceMobile(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, unmatch() { import('animation') .then((animation) => { animation.controllerMobile.destroy(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, }); // Desktop Animationen enquire.register(breakpoint.forTabletPortraitUp, { match() { import('animation') .then((animation) => { animation.triggerServiceDesktop(); animation.triggerShowcaseDesktop(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, unmatch() { import('animation') .then((animation) => { animation.controllerDesktop.destroy(); animation.tweenShowcaseDesktop.kill(); animation.tweenServiceDesktop.kill(); }) .catch(e => console.error(`${e.name} : ${e.message}`)); }, });