Jump to content
GreenSock

Search In
  • More options...
Find results that contain...
Find results in...

Leaderboard

  1. OSUblake

    OSUblake

    Moderators


    • Points

      325

    • Content Count

      5,211


  2. ZachSaucier

    ZachSaucier

    Administrators


    • Points

      290

    • Content Count

      1,986


  3. GreenSock

    GreenSock

    Administrators


    • Points

      233

    • Content Count

      14,118


  4. mikel

    mikel

    Moderators


    • Points

      131

    • Content Count

      1,161



Popular Content

Showing content with the highest reputation since 01/26/2020 in all areas

  1. 7 points
    Hey @alexandrosb, If you position all elements in one SVG - including the paths for the animation - you will definitely make it easier for yourself. https://codepen.io/mikeK/pen/WNvoyor Good Appetite ... Mikel
  2. 6 points
    Fun little animation! The distribute util is the coolest thing ever, right @Carl ? Caching is a very good technique to improve performance, but I think an easier solution is to just record the ending transformations from the wiggle animation, and then create a timeline from those values. https://codepen.io/osublake/pen/6e1e0338d8708ea850166b8d0fafab4a
  3. 5 points
    GSAP does not require IDs. It would be quite limiting if it did. If an animation does not work on mobile, then it's probably a logic problem completely unrelated to gsap. I have no idea why he said that because it's just... It's almost laughably wrong. You've always been able to animate SVG with GSAP inside any browser that supports SVG, mobile or desktop. And yes, even as a PWA.
  4. 5 points
    Hey @alexandrosb, A green GSAP dragon can do almost anything https://codepen.io/mikeK/pen/RwPKKaP Happy tweening ... Mikel
  5. 5 points
    Don't use SVG 🤷‍♂️ People always ask about how to improve their gsap code thinking it will improve performance. It usually won't. GSAP code is already optimized, so you really don't need to worry about it unless you're creating a bunch of animations or you're doing complicated stuff in onUpdate/ticker callbacks. That doesn't mean you can do whatever you want, it just means you typically don't need to worry about micro-optimizing it. Performance problems are almost always related to what you are animating... like 99.9999% of the time. Not only the medium, like SVG, but what properties you are animating. For example, animating x/y is much faster than animating left/top. The only thing I can really recommend changing in your code is to get rid of all your setTimeouts. It won't help with performance, but setTimeout is not synced with animations, and weird stuff can happen if you change tabs. Using .delayedCall() is better for animations. https://greensock.com/docs/v3/GSAP/gsap.delayedCall() Or even better. Just return timelines from your animateTrees function. gsap.timeline() .add(animateTrees("start")) .add(animateTrees("end")) .call(destroyTrees, [15]); Check out this article about using functions. https://css-tricks.com/writing-smarter-animation-code/ And I would probably add all the html in one chunk for faster startup/parsing. let html = ""; for (var i = 0; i < count; i++){ html += Math.random() > 0.25 ? tree1 : tree2; // trees.insertAdjacentHTML('beforeend', Math.random() > 0.25 ? tree1 : tree2); } trees.insertAdjacentHTML('beforeend', html); Also, you can cleanup your SVG strings by using template literals. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Multi-line_strings var tree2 = `<svg class="tree" viewBox="15 -40 20 40"> <path class="trunk" d="m25,22 l-0.5,15 a1,1 0 0,0 1,0 l-0.5,-15"/> <path d="m25,18 a10,10 0 0 1 -2,6" class="left"/> <path d="m25,21 a5,5 0 0 1 -2,3" class="left"/> <path d="m25,18 a15,15 0 0 0 3,9" class="right"/> <path d="m25,23 a6,6 0 0 0 2,3.5" class="right"/> <path d="m25,21 a8,8 0 0 1 -4,8" class="left"/> <path d="m25,23 a6,6 0 0 1 -3,6" class="left"/> <path d="m25,24 a9,9 0 0 0 6,8" class="right"/> <path d="m25,26 a8,8 0 0 0 5,6.5" class="right"/> <path d="m25,29 a8,8 0 0 0 3,3.5" class="right"/> <path d="m25,25 a9,9 0 0 1 -6,9" class="left"/> <path d="m25,27 a8,8 0 0 1 -5,7.5" class="left"/> <path d="m25,28 a7,7 0 0 1 -3,6.5" class="left"/> </svg>`;
  6. 5 points
    No. I just looked at your zip file, and it looks like you are trying to replay the scrollIndicationAnimation timeline. That obviously won't work because the original elements aren't inside the page anymore. You would have to create a new timeline to target the new elements.
  7. 5 points
    Hey @c05dk, A little help https://codepen.io/mikeK/pen/JjdYpEX Happy tweening ... Mikel
  8. 5 points
    Here's an example of scaling an svg to fill the screen. The path data is based on a 100 x 100 area. The key to getting it to scale asymmetrically is with the preserveAspectRatio="none" attribute on the <svg> element. Click anywhere to run the animation. https://codepen.io/osublake/pen/BYwgBg Taken from this thread.
  9. 5 points
    Ha. Yeah, both posts were edited. The second post about using the MorphSVGPlugin's path filter, which you really don't need to use anymore as you can define a function for canvas rendering. https://codepen.io/GreenSock/pen/WYWZab
  10. 5 points
    Just define path data. You can scale geometry. If you created path data for a 1000 x 1000 area, and now you need to it fit a 400 x 600, you would scale the path down using these values. var scaleX = 400 / 1000; var scaleY = 600 / 1000; Depending on the medium, you might have to scale every coordinate in the path. point.x *= scaleX; point.y *= scaleY;
  11. 5 points
    But if the event target is a node (which is normally the case) you can use parentNode to get the parent element. parentElement is not supported in IE if the target is an element. On the other hand if you're using react why not create a ref for the title element you want to select and use that to get it's content: // In the component's logic let handleClick = () => { console.log(this.myTitle.innerHTML); } // In the JSX <title ref={title => this.myTitle = title}>Title Text In Here</title> Even if you're dynamically adding DOM elements to the JSX, you can still find ways to create a ref and target them in an event handler. As Blake mentions a reduced live demo in codesanbox or stackblitz would be very helpful to see what you're trying to do. Happy Tweening!!!
  12. 5 points
    Hola @Comunica+A, ... or you analyze and fork this concept of our famous @Diaco https://codepen.io/MAW/pen/QbgLmV Happy drawing ... Mikel
  13. 5 points
    Your ".box" element is covered by rest of the content, so mouse never moves over it. Try setting event on ".home" or some other element that won't be covered content, ".home" is container so it should work fine. Load TweenMax(or any other library that your code depends on) before your code. The TweenMax version you are using is really old, if you want to use GSAP 2 then use version 2.1.3 or use GSAP 3. https://cdnjs.com/libraries/gsap/3.1.1
  14. 5 points
    Ah yes, that's because that element is a <g> which acts a bit differently. I'll work on a fix for the next release, but in the meantime you can just use the element's bounding box as offsets: https://codepen.io/GreenSock/pen/30a3d282ea85251bd63eb59f8c2e4db5?editors=0010 Just keep in mind that in the next release with the fix in place, you'll want to remove those offsets.
  15. 5 points
    Hey @Karma Blackshaw, You could use DrawSVGPlugin and MotionPathPlugin. Here is a quick example https://codepen.io/mikeK/pen/RwNmVPr Happy fishing ... Mikel
  16. 4 points
    Perhaps, although I do see in his code that he disables some animations for mobile. On line ~142. // disables scene animations for Phones if( !/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(window.navigator.userAgent) ) { Animation.sceneAnimation(); } It really depends on how bad the performance is. Putting SVGs inside a div can really help if you are doing transforms, like changing the position, rotation, or scale of an element. If you're doing an SVG animation that requires morphing or drawing a stroke, then putting it inside a div probably won't help out that much if your artwork is simple. Another problem with putting SVGs inside a div is that it might be hard to align stuff properly for responsiveness. So it really depends on what you are doing. There is no is hard rule. My approach would be Try it out with everything inside an SVG If that doesn't work, try putting stuff inside a divs If that doesn't work, try simplifying your artwork and animations, and redo the steps above If that doesn't work, it's time to brush on your canvas/webgl skills 😉
  17. 4 points
    Yeah, shrug, I can't remember the last time gotoAndPlay() was referenced anywhere on this site. It was deprecated ages ago. I'm guessing very close to when the JS flavor first came out when parity with AS3 had some value. And yes, gotoAndPlay() is still part of the CreateJS API to control and Animate timeline.
  18. 4 points
    I know it wont help you and may even confuse you further, but I just wanted to post this example to show you how fast canvas can execute. https://codepen.io/rlemon/pen/qpFIn
  19. 4 points
    Hey @Comunica+A, from the docs: end Number - The position along the path at which to end, where 0 is the beginning, 1 is the end, and 0.5 is in the middle. It can be any positive or negative decimal number, including a value that's less than the start (which would make the object travel backwards). For example, 0.3 would have the element end at the 30% point along the curve. 1.5 would make it loop around back to the beginning and stop at the halfway point. Default is 1. gsap.to("#balloon", { //progress:myDistance, duration: 4, ease: "power1.inOut", motionPath:{ path: "#path", end:0.02 // = 2 % } }); Happy ending ... Mikel
  20. 4 points
    You're welcome, you might gain something from this example which uses Navigation Timing API. https://codepen.io/ahsanrathore/post/accurate-page-progress-bar Just ditch the use of JQuery and CSS animation, instead using GSAP! 😀 Let us know if you make something fun.
  21. 4 points
    I saw this post the other day then forgot about it, but intended to mention another approach you might be interested in. You could look into leveraging the Navigation Timing API. https://developer.mozilla.org/en-US/docs/Web/API/Navigation_timing_API It has really good support https://caniuse.com/#feat=nav-timing It allows you to give a good page (size/preload) representation. Somewhat odd that I don't really remember seeing it mentioned here? ¯\_(ツ)_/¯ You could always hide it so you only see it once and not on page reload using localStorage, etc., https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage So @AslanGoi maybe its somthing you would like to look into or consider also.
  22. 4 points
    Hey pmillerk88 and welcome to the GreenSock forums! Thanks for being a Club GreenSock member. The biggest issue is that you aren't calling any of the functions that you created The second biggest issue is that the way you pass parameters into a callback function (like onStart) has changed in GSAP 3. I recommend that you just have an animateTrees() function that does the staggering of your animation. Some other notes: In a lot of places you do .to($("someText"), ...). You don't need to do that, GSAP uses .querySelectorAll() under the hood so you can just pass the "someText" part. The quotes around individual, non-string or complex value aren't needed (like height:"53"). Why use jQuery's .css() when you can use GSAP's .set()? You don't really need jQuery these days. If you're using JS to generate the trees, why use SCSS to edit the properties? It'd be more dynamic if you just used JS. Since you're using JS to generate the trees, why have set SVG for each tree? You could generate the branches using a function. It doesn't make much sense to have a bunch of different SVG elements - why not just put all the trees in one SVG? This sort of thing would probably be better done in Canvas which performs better with lots of elements. https://codepen.io/GreenSock/pen/eYNdQbO?editors=0010
  23. 4 points
    Hey Yarchick and welcome to the GreenSock forums! The best way is probably to create two tweens, using the distance calculation as a part of the duration calculation. Modifying a demo I made for another person, you could do it this way: https://codepen.io/GreenSock/pen/vYOXVbO?editors=0010 Or even better, use the .getRelativePosition() function of MotionPathPlugin that will be in the next release of GSAP to do most of the calculations for you! https://codepen.io/GreenSock/pen/ExjgdMr?editors=0010
  24. 4 points
    Hey Matt and welcome to the GreenSock forums! My goodness, that is a lot of data. This issue has nothing to do with GSAP (or even ScrollMagic which isn't a GreenSock product by the way). The same performance issue occurs if you remove both GSAP and ScrollMagic: https://codepen.io/GreenSock/pen/JjdRZJe?editors=0010 Hernan, the creator of Lottie, mentioned that Removing the need for filters and masks (perhaps overlaying the text with black and animating those black parts to reveal the text) would improve your performance, as would using a sprite sheet, but besides changing your approach there's not much else you can do.
  25. 4 points
    You have the params in the wrong order, and doing it like that will cause the time to drift the longer it runs. This way will give you consistent timing. gsap.to({}, { repeat: -1, duration: 1, onRepeat: myFunc });
  26. 4 points
    True My fault. @akapowl After looking into it, I realized that the issue is because the targets of the timeline don't exist when you navigate back to the page. What I mean is that when you load the index, the timeline is created and played. When you go to the test page, the targets of the timeline are removed from the page. Then when you go back to the index, the targets get added again to the page and the timeline plays correctly but the targets that the timeline is referencing are the old ones that were removed. You need to create a new timeline each time the page loads, you can't reuse old timelines because the targets get removed. https://codepen.io/GreenSock/project/editor/ZybaPo
  27. 4 points
    Hey Andrew. Addressing your question, it might be better to determine how many repeats are necessary for the given height. That way you can have a different animation at the end of the timeline without too much issue. Otherwise it's going to be hard to deal with jumps from whatever state it's in when the last animation starts. As an aside, your code could likely benefit from being more DRY (don't repeat yourself). It looks like you tried to use GSAP 3's default behavior but it wasn't working because you included the duration as the second parameter instead of inside of the vars parameter. For defaults to work, it needs to be in the vars parameter I also recommend including ease: "power1.out" in your defaults so you don't have to have that every time. I might approach this situation a little differently. I don't think my way is necessarily better, but it does seem more straightforward (to me at least) and concise. Since you have an animation that has a state that repeats within itself, you could loop through that state (I think that's what you're trying to do with the infinite section that you have?). Knowing that, once you figure out the position where it could repeat, you could have the scroll animation only play that part of the animation as it scrolls. For the intro animation, you could animate the first part of your scroll animation (for ease I didn't match your start animation but you could do something like that as long as you have a section that syncs up to loop). A basic version of my approach is here: https://codepen.io/GreenSock/pen/oNXbXOw?editors=0010 I use a tween for the repeating animation but you could switch to a timeline so you can have a varied intro instead if you'd like. I didn't add an outro animation but I left a place for you to add it. In my version instead of calculating the number of repeats you just find the scroll position that you need (i.e. N pixels from the bottom) and then, once that point is reached, instead of looping instead do the outro animation. You could even add some logic to sync up the outro start position with the end of your loop but I didn't implement that. Note that I also shortened your CSS by a bit and made the text relative to the viewport's height.
  28. 4 points
    Welcome to the forum @carlos.rosales. You can use Local Storage or Session Storage, see the below thread discussion. https://greensock.com/forums/topic/17928-stop-animation-from-playing-when-page-is-already-visited
  29. 4 points
    Hey @BrownsFanForLife, The path is exclusive of the X. Therefore, the trigger area is also limited to the gray area. Here is a 'slightly larger' example: https://codepen.io/mikeK/pen/gOppZYP Simply place a larger circle over it as a trigger object. For the above case test <rect id="button" width="300" height="120" style="fill:transparent" /> Happy tweening ... Mikel
  30. 4 points
    Yeah, I know you are trying to make it approachable, and that's hard because people want to jump right into the cool stuff. All I can say is that the majority of questions on this forum usually aren't GSAP questions at all. They mostly seem to be general JavaScript questions. It's only been around for a couple of years, so a lot of people don't know about it. In your demo it does, but having a labels object also has it pros. For example, it is much easier to get and set values in an object because you don't need to use an array index to find the label. //get var time = tl.labels.myLabel // set tl.labels.myLabel = 4;
  31. 4 points
    ^ What no GSAP? ¯\_(ツ)_/¯ 😉 @Cassie also has a nice write up on that (performant or not) https://www.cassie.codes/posts/creating-my-logo-animation/ Here is a more basic SVG Rect version of CSS Only, I miss Anonymous posts. https://codepen.io/anon/pen/VGEYEa Welcome to the forum @Comunica+A on a basic level maybe something more like this for chasing in your example? var tl = new TimelineMax({repeat:-1}); tl.fromTo(".Neon", 1, {drawSVG:"0% 0%"}, {drawSVG:"0% 100%", ease:Power4.easeIn}); tl.to(".Neon", 1, {drawSVG:"100% 100%", ease:Power4.easeOut}); For a more advanced approach to chasing have a look at this thread and article about chasing by @PointC https://greensock.com/forums/topic/19030-how-to-create-seamless-loop-of-svg-rect/ [some of these codepens in this thread by @PointC don’t seem to work anymore but I didn’t investigate why?] https://codepen.io/PointC/post/seamless-loop-svg-stroke-animations You could also look into Canvas or Pixi, etc., as @OSUblake demonstrates below. https://codepen.io/osublake/pen/XXbLer
  32. 4 points
    Hey, Just as a try, if you vary the DIACO concept, for example with motionPath https://codepen.io/mikeK/pen/XWbJdRp and here is another variant. However, I don't find an option to bypass the delay in the first tween, kill for the repeat https://codepen.io/mikeK/pen/abOzyJb Happy tweening ... Mikel
  33. 4 points
    Very nice! Former game developer here, and I can tell you that using boxes for hit detection is perfectly fine, which is what Draggrable does. Pixel perfect hit detection is rarely needed, and it can become very complicated. It can also slow your game down! https://codepen.io/osublake/pen/40b18190c60161960d8d12ff4fa71d1d https://codepen.io/osublake/pen/bb6983d03e1c3582f9aac486ab9069f8 I didn't see where you are using the throwprops plugin in your code. Anyways, the ThrowPropsPlugin has been replaced with the InertiaPlugin. Not too much difference. Just a slightly different API. https://greensock.com/docs/v3/Plugins/InertiaPlugin
  34. 4 points
    Mhhh... so this is like Gatsby but in Vue, right? I was wondering when that would happen For what I can see here: https://gridsome.org/docs/pages/#file-based-pages the structure is the same as in any regular Vue Single File Component, so using the regular syntax in it (like in Gatsby) to create your GSAP instances, using refs and everything else, should work like any other Vue App. As a personal opinion is great to see Vue growing like this, hopefully Aurelia follows as well so at some point in our lifetime we could work with standard web components and not singular-opinionated components, I know @OSUblake would also be a happy camper at that point Happy Tweening!!!
  35. 4 points
    Hi @medmedmed75 Hard to say without seeing your code in action... Can you setup a codesandbox with your react setup? With what I'm able to see: First thing, you'll want to be sure to register your ScrollToPlugin before you use it. gsap.registerPlugin(ScrollToPlugin); Also, are you seeing any errors in the console? Have you tried logging your ref (el) inside scrollTest to make sure that it is representing an element (or using an '#id' to test)? Have you tried just running the scrollTo tween without the setScrolled() or anything else to try and isolate? Hope this helps narrow it down. I run the scrollToPlugin on a lot of React projects, so I can confirm that it works.
  36. 4 points
    @andsavu @ZachSaucier It's indeed made with WebGL, with most of the magic happening in custom shaders. It's really a bit to much to get into without writing an article about it, but if you @andsavu want to learn creating these kind of things i'd recommend some of the following resources: https://webglfundamentals.org/ https://thebookofshaders.com/ https://threejsfundamentals.org/threejs/lessons/threejs-fundamentals.html Also https://tympanus.net/codrops/ have some great tutorials on the topic. Oh and @ZachSaucier thx for the resize heads-up, will fix it:)
  37. 4 points
    Very interesting - the "back.in" ease would return 0.999999999999998 when feeding in a progress of 1, so that's why autoAlpha never quite triggered the flip to hidden. Gotta love floating point math issues. I've updated that in the next release which you can preview at https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js Better? Good catch! And thanks for the reduced test case.
  38. 4 points
    Use the amount property inside a stagger object. https://codepen.io/GreenSock/pen/vYBRPbO
  39. 4 points
    i had to take a closer look at this tail wave ....not done yet with interactivitiy, but looks good so far https://codepen.io/Illustraktor/pen/bGdGoMd
  40. 4 points
    Hey @shrinky, Welcome to the GreenSock Forum. Note: A common mistake is to forget to use camel case representations of the properties, so instead of “font-size”, you’d use “fontSize”. “background-color” should be “backgroundColor”. Try it. If you have problems ... please your case as CodePen. Happy tweening Mikel
  41. 4 points
    To get a clean result when tweening "attr" and path points you need the same number of points throughout from start to end. Otherwise yes you will typically get weirdness with varying numbers of points with that approach. The MorphSVG plugin would easily help you if you need to use varying numbers of points like you have shown.
  42. 4 points
    well i know i was totally attracted by the other 'wavy' techniques in opened tabs, so .. i missed exactly what i wanted... ( i remember exactly, that i saw the 'cat' with no animation in the preview, and closed the tab ..like an idiot. So it serves me right, 'running in circles'... but no problem. i learned a lot the last days, i should complete my little path d animation-defintion thing,.... after @mikel ´s info.... it is of course more complex, than i foolishly thought. ...so thank you... i should at least do one cat´s tail animation... @Sahil´s version is of course 'inspiring' too 😀 ...and, here is dangerous 'Harry', the furry bumbleFly.He will probably get a new haircut- and what not - soon. This is the first try to animate stuff, triggered by scrolling, rather than hovering or clicking. https://codepen.io/Illustraktor/pen/dyobmEO
  43. 4 points
    It really shouldn't matter if you are including the plugin in a script tag. You can double check to make sure it's loaded by logging this out before you use it. console.log(window.com.greensock.plugins); If it's loaded and you still can't get it to work, perhaps you are using the plugin incorrectly. Make sure you are targeting an svg element that has a stroke on it.
  44. 4 points
    Hey @bertelot, Here is a nice 'pocket giude' and here a cool tool to learn how to build SVGs. Hey @ZachSaucier, In the late 1960s I learned to read quickly, especially for narrow newspaper columns with the optimal number of characters, the optimal line length and line weft. Happy reading. Makes live easier. Mikel
  45. 4 points
    The latest update to GSAP 3 was (3.1.1), but version 3 itself was released at the start of November (3 months ago) 😉 https://greensock.com/3-release-notes/
  46. 4 points
    Ok, here is how to workaround the missing definition for now. Create a .d.ts file in your project, like typings.d.ts. Then add the following code to that file. It should resolve that error for you. declare namespace gsap { function quickSetter(target: TweenTarget, property: string, unit?: string): (value: any) => void; } We'll make sure that the next release of gsap will include the quickSetter definition.
  47. 4 points
    Hey @bertelot, Of course, you can tween a path - e.g. like this https://codepen.io/mikeK/pen/zYxgdRw Happy tweening ... Mikel
  48. 4 points
    Hi Sketchin, you could use i.e. timeline for this. Would it be a solution for you ? The last parameter inserts the tween at 1 which will be respected every time you restart the timeline. var toggle = document.getElementById('toggle') toggle.addEventListener('click', toggleHandler, false) var tl = gsap.timeline({paused:true}); tl.fromTo('#square', 1, { x: 0,}, { x: 500 },1); var state = true; function toggleHandler() { if (state) { tl.play() } else { tl.reverse() } // Update state state = !state }
  49. 4 points
    Hey Andrew and welcome to the GreenSock forums! 🎆🎊🥳 This is because you're not taking the scroll offset into account. I would recommend getting the scroll position on load, getting the values you need, then resetting the scroll position to what it was before. Something like this (I upgraded you to GSAP 3 because the GSAP version you were using is very old and GSAP 3 is much better): <script src="https://cdn.jsdelivr.net/npm/gsap@3.1.1/dist/gsap.min.js"></script> <script> let triggerOffset = document.documentElement.clientHeight / 2; let sceneStart = 2000; let duration = 300; let requestId = null; gsap.set(".timeline-trigger", { top: triggerOffset }); gsap.set(".start-trigger", { top: sceneStart }); gsap.set(".end-trigger", { top: sceneStart + duration }); // SCROLL MAGIC!!! let boxes = document.querySelectorAll('.box'); let tl = gsap.timeline({ paused: true, defaults: {duration: duration} }) // The relevant part to this thread const startScrollPos = document.documentElement.scrollTop; document.documentElement.scrollTop = 0; boxes.forEach(box => { let sceneStart2 = (box.getBoundingClientRect().top) console.log('sceneStart2',sceneStart2); tl .set(box, { backgroundColor: "#64dd17" }, sceneStart2) .to(box, { rotation: 720, x: 300 }, sceneStart2) .set(box, { backgroundColor: "red" }) }); document.documentElement.scrollTop = startScrollPos; // Set timeline time to scrollTop function update() { tl.time(window.pageYOffset + triggerOffset); console.log(window.pageYOffset + triggerOffset) requestId = null; } window.addEventListener("scroll", update); update(); </script>
  50. 4 points
    Thanks @ZachSaucier That example is beautiful. But it's too much dev work for me to really grasp. After playing around with it for a while I was able to get what I wanted by overlapping the beginning and end of the Illustrator art. Here is what I have. https://codepen.io/sirhclluk/pen/mdyoMzO?editors=1010
×