Jump to content
Search Community

Tahir Ahmed

Business
  • Posts

    62
  • Joined

  • Last visited

Everything posted by Tahir Ahmed

  1. Hi @spacewindow, Take a look at this forked codepen: http://codepen.io/tah_med/pen/dGPErM and then the JS below: var tl = new TimelineMax({ repeat: -1 }); // RANDOM NUMBER MIN MAX - https://gist.github.com/timohausmann/4997906 var randMinMax = function(t, n, a) { var r = t + Math.random() * (n - t) return a && (r = Math.round(r)), r } // Returns one single Cloud by duplicating the existing Cloud element var createCloud = function(element) { var newElement = element.cloneNode(true); element.parentNode.insertBefore(newElement, element.nextSibling); return newElement; }; // Initial placement of all clouds objects var placeClouds = function(clouds) { TweenMax.staggerTo(clouds, 0, { cycle: { x: function() { return randMinMax(-200, 200); }, y: function() { return randMinMax(0, 100); }, scale: function() { return randMinMax(0.4, 1); } }, opacity: 0 }, 0); }; // Addition of all cloud elements into main TimelineMax instance var addIntoMainTimeline = function(clouds) { tl.staggerTo(clouds, 4, { cycle: { x: function() { return randMinMax(-200, 200); }, y: function() { return randMinMax(-150, -200); }, scale: function() { return randMinMax(0.4, 2); } }, bezier: [{ opacity: 0.8 }, { opacity: 0 }], ease: Power1.easeInOut }, 0); }; var clouds = function(cloud, numClouds) { var clouds; var element = document.querySelector(cloud); for (var i = 0; i < numClouds; i++) { createCloud(element); } clouds = document.querySelectorAll(cloud); placeClouds(clouds); addIntoMainTimeline(clouds); }; clouds('.dust', 4); Main takeaways are: The use of .staggerTo methods. Take a look at the documentation for more details on it: TweenMax.staggerTo() static method and TimelineMax's .staggerTo() instance method. Especially the use of `cycle` property introduced in these methods in version 1.18.0. The usage of BezierPlugin. See documentation for more details. Let us know if you have any questions after that.
  2. Hi @PetaWeb, 1. To answer your question about "have more elements to animate on one slide but less on another slide", here is what I think that should be done to cater that: Currently, the `.createTimeline()` function animates the 2 elements you were already animating. It is just a more re-usable way of doing that. Nothing else. If for example, there is a timeline that needs to animate more elements other the typical `title` and `caption` that you were previously animating, then this function alone won't deem so useful anymore. It will either need to be extended in a way to expect more elements and then animate these elements respectively or, there doesn't even need to be a need for a function and all timelines are created on a per-need basis because it may seem that the requirements for each timeline is different and unique. Having said that, you may want to share how you intend to animate the `.anotherElement3`, `.anotherElement1-5` and `.anotherElement2-5` elements. As an example of what I am talking about when I say "extend the same function to expect more elements", you could do something like: function createTimeline(title, caption, element1, element2) { var timeline = new TimelineMax({ paused: true }); if (title !== '') { timeline.from(title, *duration*, { /* whatever you want to do with it */ }, *position*); } if (caption !== '') { timeline.from(caption, *duration*, { /* whatever you want to do with it */ }, *position*); } if (element1 !== '') { timeline.from(element1, *duration*, { /* whatever you want to do with it */ }, *position*); } if (element2 !== '') { timeline.from(element2, *duration*, { /* whatever you want to do with it */ }, *position*); } return timeline; } and the usage will look like: timelines[*index*] = createTimeline('.someTitle', '.someCaption', '.someElement', '.anotherElement'); and for those you don't want to animate other elements, pass in empty strings: timelines[*index*] = createTimeline('.someTitle', '.someCaption', '', ''); Seems like an overkill but then again, it depends on what exactly are you animating and if we can optimise it even further. 2. I am not sure if I understand it correctly, the part where you say "add more gsap animations on more than just two elements". `.createTimeline()` is just a function, you can add as many elements as you'd like. Just receive them as parameters first and then do what you want to do with them, as shown above. Let me know if it helps or if you need anything clarified.
  3. Hi @PetaWeb, Take a look at the JS below: var $myCarousel = $('#carousel-example-generic'); var timelines = []; timelines[0] = createTimeline('.tlt', '.tlt2'); timelines[1] = createTimeline('.it-h3', '.it-h4'); timelines[2] = createTimeline('.title3', '.caption3'); function doAnimations(elems) { var animEndEv = 'webkitAnimationEnd animationend'; elems.each(function () { var $this = $(this), $animationType = $this.data('animation'); $this.addClass($animationType).one(animEndEv, function () { $this.removeClass($animationType); }); }); } var $firstAnimatingElems = $myCarousel.find('.item:first').find('[data-animation ^= "animated"]'); timelines[0].play(); doAnimations($firstAnimatingElems); $myCarousel.carousel('pause'); $myCarousel.on('slide.bs.carousel', function (e) { var currentSlideIndex = $(e.relatedTarget).index(); timelines[currentSlideIndex].restart(); var $animatingElems = $(e.relatedTarget).find("[data-animation ^= 'animated']"); doAnimations($animatingElems); }); function createTimeline(title1, title2) { var timeline = new TimelineMax({ paused: true }); timeline.from(title1, 0.6, { x: '-=200', autoAlpha: 0, ease: Expo.easeOut }, 0); timeline.from(title2, 0.6, { x: 200, autoAlpha: 0, ease: Expo.easeOut }, 0.1); return timeline; } Here is what has changed: Timelines are created and put together inside an array called timelines. Inside the slide.bs.carousel callback, we get the index of the upcoming slide (slide.bs.carousel event fires at the _start_ of the transition) by using jQuery's .index() helper method. We then use this index to correctly trigger the timeline present in the timelines array created earlier like so: timelines[currentSlideIndex].restart(); Here is your forked pen.
  4. Tahir Ahmed

    Dragger

    @Mustana, good to see you hear in forums as well I noticed that you are expecting to use `e` (i.e. event object) inside the `onDragEnd` and `onDrag` callbacks but as per the documentation, you need to reference the `Draggable` object by using `this` keyword. So these lines: ... if (e.x >= 400) { ... and ... var clipProp = (e.x - 10) + 'px'; ... should be changed into: ... if (this.x >= 400) { ... and ... var clipProp = (this.x - 10) + 'px'; ... The event object that you were trying to access before is the one that is made available by browsers but the properties it carries, varies between browsers. So Google Chrome has the `x` and `y` exposed and your code seemed to work just fine but the cross-browser way would be to access the Draggable object by using `this` keyword and then access `x` or any other property through it. I hope this solves your problem.
  5. Well I guess I was late Here is what I was able to do: http://codepen.io/tah_med/pen/xZxOEd?editors=001. And yes, problems are already mentioned by @GreenSock himself.
  6. jQuery doesn't seem to be loaded. Click on the gear icon inside the JS panel of your codepen, the choose jQuery from the Quick-add dropdown. And then, manually drag this newly added line above the jquery-ui.min.js line. Also, you don't need to load up two versions of TweenMax into your pen. You can remove the 1.14.2 version and only use the latest.
  7. Hi, I think you need to create separate TimelineMax (or Lite) instances for each of the animations as @Diaco aptly suggested. Below is another suggestion which, at the core of it, does create individual TimelineMax instances but some things are different: JavaScript: var shareSelect = document.querySelectorAll(".share-select"); var shareSelectButtons = document.querySelectorAll(".share-select .share-close"); var shareSelectDivider = document.querySelectorAll(".divider"); var timelines = []; var timeline = null; var shareButton = document.querySelectorAll('.share-button'); var shareClose = document.querySelectorAll('.share-close'); var length = shareButton.length; for (var i = 0; i < length; i++) { timeline = new TimelineMax({ paused: true, reversed: true }); timeline .fromTo(shareSelect[i], 0.25, { maxWidth: 0, x: -20 }, { maxWidth: 200, x: 0 }, 0) .staggerFromTo(shareSelectButtons[i], 0.5, { rotation: -10 }, { rotation: 0, ease: Back.easeOut }, 0) .fromTo(shareSelect[i], 0.5, { autoAlpha: 0 }, { autoAlpha: 1 }, 0) .fromTo(shareSelectButtons[i], 0.5, { x: -20 }, { x: 0 }, 0) .fromTo(shareSelectButtons[i], 1.1, { autoAlpha: 0 }, { autoAlpha: 1 }, 0) .fromTo(shareSelectDivider[i], 1.0, { autoAlpha: 0 }, { autoAlpha: 1 }, 0.25) .fromTo(shareSelectDivider[i], 0.5, { x: -50 }, { x: 0 }, 0) .timeScale(2.75); timelines[i] = timeline; (function(i) { shareButton[i].addEventListener('click', function() { timelines[i].reversed() ? timelines[i].play() : timelines[i].reverse(); }, false); shareClose[i].addEventListener('click', function() { timelines[i].reverse(); }, false); }(i)); } What really is happening is: The shareSelectButtons buttons are not simply targeting all the button elements inside .share-select elements but instead, it only targets .share-close button within. There is an empty array called timelines first initialised. The length is also pre-cached. Inside the loop:A TimelineMax instance is first created. All the animations that you originally defined are assigned to it but notice a difference that each of the shareSelect, shareSelectButtons and shareSelectDivider elements are referenced individually by the use of the current iterator i.e. i variable since querySelectorAll returns all the matched elements (an array), you need to properly target the respective element in a given animation, otherwise all will animate. And because, our idea is to create individual timelines, we definitely need to target individual items for those individual tweens. Hope I am making sense here. By the end of all tween additions into a timeline, the timeline itself is added into the main timelines array that we first created. Then comes the closure function. I would suggest to read up here and then come back with questions if you have any. Inside the closure, the code looks pretty much the same except that I have only gone with reversing the timeline when clicking on shareClose element instead of playing it forward or reversing it based on its reversed() state. Just makes sense to me. Your choice on this one though. Another thing to note inside this closure is that only the respective timeline instance is played thanks to the i variable when either clicked on shareButton or shareClose button. As for your question about the "delay" when reversing, it is because of the way your timeline is set up. Look at the shareSelectDivider's autoAlpha line for example that has an absolute position in the timeline that of 0.25 with a duration of 1 second. Similar thing is done for shareSelectButtons element's autoAlpha property with a duration of 1.1 seconds. All the other animations' durations are minimal in comparison. Eventually, when the animation reverses, a timeline would first start animating these longer durations and then, the more apparent shorter duration animations come into picture. Hard to explain without any visual cues. I suggest read up here. Just try to give all of them same duration of 0.5 and you will not notice any "delays". Hope this helps.
  8. Arrgh! too many right answers to choose from Thanks a lot @Jack, @Carl and @OSUblake. Thank you so much for the inspiration.
  9. How does the Ease Visualizer [Link] draws graph based on the selected ease? What properties are being animated that change the graph's points to mimic the selected ease equation? I tried to make sense of it all by looking into the source code but minified sources melt my brain even after using some online beautifiers (they cannot really beautify variable and method names of course or am I missing something?). I am trying to create something similar, for fun purposes and to quench my curiosity.
  10. I noticed that you have some random durations for each of the leaf that you create using generateParticles. And since it all of those inner timelines get added inside the main leafEmitterTl, the onComplete of leafEmitterTl will fire once every animation inside is completed. Also, generateParticles(5) will add 5 inner timelines inside the main leafEmitterTl and they are all queued after one another by default (since you are not really defining a position for each of the leaf inner timelines when adding into leafEmitterTl), hence the onComplete fires in a range between 4 and 30 seconds. Can you try to give an absolute duration (no randomness) to inner timeline of each leaf object with absolute positions (e.g. 0, rather than doing computations as you currently are), all to try to finish the main leafEmitterTl in an absolute time? Also, if you can create a codepen demo, that would really help debug.
  11. I think you need to break down your borderBottom into different parts (e.g. borderBottomWeight, borderBottomStyle and borderBottomColor) and pass those instead of the combined borderBottom that you are currently passing. I don't exactly know why does the shorthand borderBottom doesn't work here but at least you have a replacement for that. JavaScript: var navbarHeight = $(".navbar").height(); TweenMax.set($(".navbar-default .navbar-nav > li > a"), { height: navbarHeight, lineHeight: navbarHeight + 'px', borderBottomWidth: 0, borderBottomStyle: 'solid', borderBottomColor: '#000', color: "#777777", fontWeight: "bold" }); TweenMax.set($(".dropdown-menu"), { display: "block", autoAlpha: 0 }); $("ul.nav > li > a.link").bind("mouseenter focus", function() { if (!$(this).hasClass("active")) { TweenMax.to($(this), 0.3, { color: "#000000", borderBottomWidth: 3, borderBottomStyle: 'solid', borderBottomColor: '#000' }); } }); $("ul.nav > li > a.link").bind("mouseleave blur", function() { if (!$(this).hasClass("active")) { TweenMax.to($(this), 0.3, { color: "#777777", borderBottomWidth: 0, }); } }); function markActivePage(activeLinkEl) { TweenMax.to($("ul.nav > li > a.link"), 0.3, { color: "#777777", borderBottomWidth: 0 }); TweenMax.to(activeLinkEl, 0.3, { color: "#ee3124", borderBottomWidth: 3, borderBottomStyle: 'solid', borderBottomColor: '#ee3124' }); } $('ul.nav > li > a.link').click(function(e) { e.preventDefault(); $('ul.nav > li > a').removeClass('active'); $('.dropdown-menu > li > a').removeClass('active'); $(this).addClass('active'); markActivePage($(this)); }); $('.dropdown,.dropdown-menu').bind("mouseenter focus", function() { TweenMax.to($(".dropdown-menu"), 1, { display: "block", autoAlpha: 1 }); }); $('.dropdown,.dropdown-menu').bind("mouseleave blur", function() { TweenMax.to($(".dropdown-menu"), 1, { display: "block", autoAlpha: 0 }); }); Also, as per the documentation of CSSPlugin [Link], as of 1.8.0 version, you don't necessarily need to use the `css:{}` wrapper object around the properties you wish to animate. You could simply skip that and it would still work. Hope this helps.
  12. Ah! that is a good technique @Jonathan I was aware of animating .progress() or .time() properties of a tween / timeline within another tween and have actually used this technique many times before but I completely forgot about using that in this scenario. Thanks a bunch.
  13. Probably a weird feature request but would it be possible if SteppedEase could utilise similar functions such as template in RoughEase? The scenario is that I want to use SteppedEase but want the stepping to start to happen gradually and by the end of the animation, reach the highest point i.e. kind of like what Expo.easeOut equation produces. The closest I could get was to use RoughEase but it creates a rough animation, as it is supposed to. SteppedEase is orderly but very linear and RoughEase is very random and well, rough. P.S. I am aware of the randomise flag in RoughEase.
  14. @Jack, good to hear that. I'll wait of course
  15. I was wondering if there should be a config available for Bounce ease as well like the ones that are available in Elastic as well as Back eases. The use-case for example is to control the number of bounces as well as the amplitude, for lack of a better word i.e. the force with which it bounces back everytime it hits the floor. Example: jsFiddle. Thoughts?
  16. Tahir Ahmed

    Gallery

    This may help: http://codepen.io/tah_med/pen/RWgPZY. HTML: <section id="gallery"> <div class="cell"> <div class="image">this</div> </div> <div class="cell"> <div class="image">this</div> </div> <div class="cell"> <div class="image">this</div> </div> <div class="cell"> <div class="image">this</div> </div> </section> CSS: html { width: 100%; height: 100%; }body { margin: 0; padding: 0; height: 100%; width: 100%; } #gallery { background-color: #000000; width: 100%; height: 100%; position: absolute; } .cell { background-color: #F0F; width: 25%; height: 25%; cursor: pointer; float: left; overflow: hidden; } .image { background-color: #FF0; width: 100%; height: 100%; position: relative; float: left; } JavaScript: var cells = document.getElementsByClassName('cell'); var numCells = cells.length; var duration = 0.8; var easeOut = Power2.easeOut; var easeIn = Power2.easeIn; for (var i = 0; i < numCells; i += 1) { cells[i].addEventListener('mouseover', inFunction, false); cells[i].addEventListener('mouseout', outFunction, false); } function inFunction(e) { TweenMax.to(e.target.parentNode, duration, { autoAlpha: .5, ease: easeOut }); TweenMax.to(e.target, duration, { scale: 1.2, ease: easeOut }); } function outFunction(e) { TweenMax.to(e.target.parentNode, duration, { autoAlpha: 1, ease: easeIn }); TweenMax.to(e.target, duration, { scale: 1, ease: easeIn }); }
  17. Tahir Ahmed

    Gallery

    ooh! same `id` applied to a number of elements i.e. `cell` and `image`. IDs are supposed to be unique. May be you intended to use `class` instead?
  18. @zoomclub, you need to stop GASP-ing and start GSAP-ing I kind-a like Green-Animation-Sock Platform for a name though
  19. Here is an idea for you to try out: Codepen. The idea is that you have timeline objects for all three of your sliding elements and you basically just control the progress of each of them based on which button is clicked. JavaScript: (function() { var btnLeft = $('[data-btn="left"]'); var btnRight = $('[data-btn="right"]'); var one = $('.js-census'); var two = $('.js-enviroment'); var three = $('.js-public'); var tlOne = new TimelineMax({ paused: true }); var tlTwo = new TimelineMax({ paused: true }); var tlThree = new TimelineMax({ paused: true }); var duration = 1; var ease = Power2.easeInOut; var opacity = 0.1; TweenMax.set([one, two, three], { position: 'absolute', top: '50%', left: '0%', yPercent: -50, xPercent: -50 }); tlOne.fromTo(one, duration, { xPercent: -80, opacity: opacity }, { left: '50%', xPercent: -50, opacity: 1, ease: Power0.easeNone }); tlOne.to(one, duration, { left: '100%', xPercent: -20, opacity: opacity, ease: Power0.easeNone }); tlTwo.fromTo(two, duration, { opacity: opacity }, { left: '50%', opacity: 1, ease: Power0.easeNone }); tlTwo.to(two, duration, { left: '100%', opacity: opacity, ease: Power0.easeNone }); tlThree.fromTo(three, duration, { opacity: opacity }, { left: '50%', opacity: 1, ease: Power0.easeNone }); tlThree.to(three, duration, { left: '100%', opacity: opacity, ease: Power0.easeNone }); tlOne.progress(0.5); tlTwo.progress(0); tlThree.progress(1); function init() { btnLeft.on('click', rotateLeft); btnRight.on('click', rotateRight); } function rotateLeft() { slideLeft(tlOne); slideLeft(tlTwo); slideLeft(tlThree); } function rotateRight() { slideRight(tlOne); slideRight(tlTwo); slideRight(tlThree); } function slideLeft(tl) { var progress = tl.progress(); if (progress > 0 && progress <= 0.5) { TweenMax.to(tl, duration, { progress: 0, ease: ease }); } else if (progress > 0.5 && progress <= 1) { TweenMax.to(tl, duration, { progress: 0.5, ease: ease }); } else { TweenMax.to(tl, duration, { progress: 1, ease: ease }); } } function slideRight(tl) { var progress = tl.progress(); if (progress >= 0 && progress < 0.5) { TweenMax.to(tl, duration, { progress: 0.5, ease: ease }); } else if (progress >= 0.5 && progress < 1) { TweenMax.to(tl, duration, { progress: 1, ease: ease }); } else { TweenMax.to(tl, duration, { progress: 0, ease: ease }); } } // init(); })(); Code can be improved surely though i.e. repetitions could be avoided.
  20. @Jack, glad the fix is coming soon. stagger methods have become really powerful with this 1.18.0 update and their power really shines when we have got as much control and access we can have to the individual tween element, to completely get rid of a loop. This delay was just an example of that. I have got a few more ideas bubbling up, will create new threads for them once they settle down a bit @OSUblake, nice one
  21. Oh ok! Hadn't tested with TimelineMax so didn't know it was working with it. Thanks a bunch guys. For now, TimelineMax will do but I will be surely waiting for the TweenMax fix then Thanks again. Tahir.
  22. Hello again @Carl and @OSUblake, thanks for looking into this. Take a look at this jsFiddle for example and notice the use of delay in there. I expect to have a certain delay in operation. This is an example scenario by the way but I would love to know how to make this work in this case. Code is as below: var numDIVs = 100, divs = [], div = null, width = 2, height = 40, margin = 10, gutter = 2; for (var i = 0; i < numDIVs; i += 1) { div = document.createElement('div'); document.body.appendChild(div); divs.push(div); } TweenMax.staggerTo(divs, 0, { position: 'absolute', top: margin, cycle: { left: function(index) { return margin + index * width * gutter; } }, width: width, height: height, backgroundColor: '#cc0' }, 0); TweenMax.staggerTo(divs, 1, { cycle: { delay: function(index) { // this block doesn't seem to be working return index; // or perhaps I am missing something simple }, rotation: function(index) { return index * 10; } } }, 0); Let me know.
  23. I see. Thanks @OSUblake. Right after posting the question, I did find out that the overshoot for Back and amplitude and period for Elastic eases are animatable via cycle property. My intention was to use them in a function utilising their index parameter. As for the "GSAP specific ones that might not work", I would actually like to know which ones, out of curiosity. True, that although stagger parameter is for adding delay, but the delay that gets added is very linear / incremental i.e. it starts off from 0 all the way to the length of the objects provided. I am interested in doing something weird, say randomisation, with delay. Or may be, again, utilising the index and do something fancy with it. I understand that this may be an edge-case scenario and perhaps I am asking for too much bloat and desperately trying to totally get rid of the for loops. I am also sure that @Jack would definitely have thought about that and would have had a really good reason not to include it, performance perhaps.
  24. Hi, I was wondering if cycle could handle properties like delay or the overshoot value of a Back ease for example. Or to put it the other way, what are the properties cycle can animate?
×
×
  • Create New...