Share Posted December 5, 2016 Hi,I created this page several months ago and everything was working great on all major browsers. Now when I check it on chrome and click on "See their time fly", it will start the animation and look good until it starts to render weird and only show part of a photo. Eventually it just kind of breaks. Do you have any idea why this is happening? This page continues to work great on Safari and Firefox. Here is my code: var photoItem = $('.photo_item'), groupOne = $('.group-one .photo_item'), groupTwo = $('.group-two .photo_item'), groupThree = $('.group-three .photo_item'), groupFour = $('.group-four .photo_item'), groupFive = $('.group-five .photo_item'), beforeLastPhoto = $('.photo_item.mod-before-last'), pulseEl = $('.photo_item.mod-last'), lastPhoto = $('.photo_item.mod-last'), currentItem = 0, rotateValues = ["-20deg", "20deg", "-10deg", "10deg", "0deg"], widthOffset = 100, heightOffset = 100, containerWidth = $('.photos').width() - widthOffset, containerHeight = $('.photos').height() - heightOffset, masterTimeline = new TimelineMax(), replayTimeline = new TimelineMax(); Draggable.create(photoItem, {type:"x,y", edgeResistance:0.2 }); $('.js-btn').one('click', function(){ start(); }); $('.js-restart-btn').on('click', function() { restartTimeline(); }); function start() { $('.js-btn').addClass('is-not-visible'); $('.js-restart-btn').addClass('is-visible'); masterTimeline.set(photoItem, { clearProps:"zIndex" }) .add(beginGroupOne()) .add(beginGroupTwo(), "-=.7") .add(beginGroupThree(), "-=.5") .add(beginGroupFour(), "-=.3") .add(beginGroupFive(), "-=.05"); } function beginGroupOne() { var tl = new TimelineMax(); groupOne.each(function(index, element) { tl.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 }) }); tl.staggerTo(groupOne, 1.25, { scale:1, autoAlpha:1, ease: Expo.easeOut }, .5, 0); return tl; } function beginGroupTwo() { var tl = new TimelineMax(); groupTwo.each(function(index, element) { tl.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 }) }); tl.staggerTo(groupTwo, .75, { scale:1, autoAlpha:1, ease: Expo.easeOut }, .3, 0); return tl; } function beginGroupThree() { var tl = new TimelineMax(); groupThree.each(function(index, element) { tl.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 }) }); tl.staggerTo(groupThree, .5, { scale:1, autoAlpha:1, ease: Expo.easeOut }, .2, 0); return tl; } function beginGroupFour() { var tl = new TimelineMax(); groupFour.each(function(index, element) { tl.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 }) }); tl.staggerTo(groupFour, .25, { scale:1, autoAlpha:1, ease: Expo.easeOut }, .1, 0); return tl; } function beginGroupFive() { var tl = new TimelineMax(); groupFive.each(function(index, element) { tl.set(element, { x: getRandomInt(100, containerWidth), y: getRandomInt(50, containerHeight), rotation: getRandomRotate(), xPercent: -50, yPercent: -50 }) }); tl.staggerTo(groupFive, 1.75, { scale:1, autoAlpha:1, ease: Expo.easeOut }, 1, 0); tl.to(beforeLastPhoto, 1.75, { x: -65, y: 115, xPercent: 0, yPercent: 0, scale:1, rotation: -20, autoAlpha:1, ease: Expo.easeOut }, "-=.5") .to(lastPhoto, 1.75, { x: 0, y: 0, xPercent: -50, yPercent: -50, scale:1, rotation: 10, autoAlpha:1, ease: Expo.easeOut }, "-=.5") .addCallback(finished, "+=1"); return tl; } function moveOff() { var tl = new TimelineMax(); tl.to([groupOne], 1.5, { yPercent: -1000 }, 0) .to(groupTwo, 1.5, { xPercent: -1000, }, 0) .to([groupThree, beforeLastPhoto], 1.5, { yPercent: 1000 }, 0) .to([groupFour, groupFive, lastPhoto], 1.5, { xPercent: 1000 }, 0); return tl; } function finished() { pulseEl.addClass('is-animating'); } function restartTimeline() { masterTimeline.set(photoItem, { clearProps:"zIndex" }) pulseEl.removeClass('is-animating'); replayTimeline.add(moveOff()) .addCallback(restart); } function restart() { masterTimeline.restart(); } function getRandomRotate() { return rotateValues[Math.floor(Math.random() * rotateValues.length)]; } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } See the Pen by homepage (@homepage) on CodePen Link to comment Share on other sites More sharing options...
Share Posted December 5, 2016 I didn't have time to look through all the code, but I wanted to point out that in my experience, Chrome typically refuses to render transforms on elements that have display:inline. Perhaps that's the problem here? 1 Link to comment Share on other sites More sharing options...
Share Posted December 6, 2016 Hello schmolzp and welcome to the GreenSock Forum! Jack is right.. according to the CSS spec.. see below link: https://drafts.csswg.org/css-transforms-1/#terminology transformable element A transformable element is an element in one of these categories: an element whose layout is governed by the CSS box model which is either a block-level or atomic inline-level element, or whose display property computes to table-row, table-row-group, table-header-group, table-footer-group, table-cell, or table-caption [CSS21] So you need to have a box model present in order for the browser to calculate the element properly. When you use display:inline it is not a block-level element. If you do use display:inlein you will probably need to define a height and width. But still to play it safe use display:block. Hope this sheds some light on why you see that issue in Chrome. Resources: https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements https://drafts.csswg.org/css-transforms-1/#terminology 5 Link to comment Share on other sites More sharing options...
Author Share Posted December 6, 2016 Thanks for the reply. On the elements I am animating in, they are display: block, so I don't think that's the issue here. The strange thing is that when you click on the button, it will start animating great and then once it gets to the third batch of photos it starts to screw up. Several months ago, it was working great in Chrome. It would do exactly as it does now in Firefox/Safari. Are you able to see the issue I am talking about in Chrome? Thanks again for any help you can provide! Link to comment Share on other sites More sharing options...
Share Posted December 6, 2016 Hi schmolzp, Just to say that I do see the issue you're reporting. I don't have the time to look into it right now but will do some investigating later to see if I can see what might be the issue. If, in the meantime, you could setup a little reduced-case demo that replicates the issue in CodePen or JSFiddle, it would be great as it would save me a to of time going over all the unrelated code on the site. You might end up discovering the issue yourself while deconstructing it - it has happened to me several times in the past. 2 Link to comment Share on other sites More sharing options...
Share Posted December 6, 2016 Hello schmolzp, By default the <img> element has a value of display: inline that it uses for its computed value. You might have display:block in the CSS stylesheet. But the inline style of the <img> element shows display:inline in the browser inspector.. <img style="display:inline;" class="lazy" alt="" src="/homepage/2016_graduation/images/_first/02_lind_sayjane-4.jpg"> x That inline style will override the display property you have in your stylesheet! You can override the inline style by using the CSS !important declaration. .photos .group figure > img { display: block !important; } Also to get the best help you should really create a reduced codepen demo otherwise it will be hard for us to see your code in context. And helps so we dont have to go through all the unrelated code you have on your site. In codepen we can test your code live in an editable environment. 4 Link to comment Share on other sites More sharing options...
Author Share Posted December 7, 2016 Thanks! I have created a reduced codepen demo. Hopefully, that will help you guys pinpoint the issue on Chrome. I also added .photo_item > img { display: block !important; } to the pen like you said. Let me know what you think. See the Pen zojmPw by schmolzp (@schmolzp) on CodePen Link to comment Share on other sites More sharing options...
Share Posted December 7, 2016 Hello Again schmolzp This should fix your issue. See the Pen zojeoo by jonathan (@jonathan) on CodePen It wasn't really a GSAP or Chrome bug. Just the way you were using the CSS will-change property Why this happens: The issue in Chrome was that you are using the will-change property Line 20 for CSS rule .photo-item in the CSS panel. So i commented out the will-change property since it will cause more harm then good. So you don't need it! will-change: transform, opacity; /* will-change: transform, opacity; */ You wont need the will-change property. It should only be used in certain instances as a last resort. And can cause havoc when used. https://developer.mozilla.org/en-US/docs/Web/CSS/will-change The will-change property was being applied to many multiple elements and was causing the clipping of the Polaroid elements towards the end of animating the last several elements. That is why you only saw the clipping and fragmentation of elements rendering to the last elements being animated in. will-change has some rules to its use. So in your case you don't need it since it is causing rendering issues, and your applying it to tremendous amount of DOM elements: Don't apply will-change to too many elements. Use sparingly. Don't apply will-change to elements to perform premature optimization. Be aware, that will-change may actually influence the visual appearance of elements That is why it was causing your issue. If you need to help GSAP record all your values upfront to improve performance you can start your masterTimline instance in a paused state by setting paused:true masterTimeline = new TimelineMax({ paused:true /* start timeline in paused state */ }), in your start() function i added the last two methods progress() and play() .add(beginGroupOne()) .add(beginGroupTwo(), "-=.7") .add(beginGroupThree(), "-=.5") .add(beginGroupFour(), "-=.3") .add(beginGroupFive(), "-=.05") .progress(1).progress(0) /* pre-record values and properties for optimazation */ .play(); /* play timeline */ progress(1) moves the playhead to the end and then back again to start using progress(0) to allow GSAP to pre-record the start and end values. Hope this helps! Happy Tweening 5 Link to comment Share on other sites More sharing options...
Share Posted December 7, 2016 Good find, Jonathan. Also, there's an article I wrote about the dangers of will-change at http://greensock.com/will-change that might be worth a read. It's a property that was intended to help animators, but it actually does the opposite in many situations which is quite disturbing. I hope the browser vendors "will change" the way they implement that feature (see what I did there?) 4 Link to comment Share on other sites More sharing options...
Author Share Posted December 7, 2016 Thank you so much! You know, it's kinda funny. As I was constructing the codepen, I noticed and remembered that I had 'will-change' on that selector. I remembered how will-change was supposed to be helpful (in the beginning) but became much more harmful for developers to use. I deleted 'will-change' on my project to test it out and for some reason, it wasn't changing anything. But now that I try it again, it seems to be back to normal and working correctly for me. Also, thanks for the little tip on performance with starting the timeline in a paused state. This will help a lot! You guys are the best! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now