Search code examples
javascriptsafarigsap

How can I smoothen rotateY transform in Safari?


I first tried using CSS, but when I was informed that it looks buggy on Safari, I tried with Greensock's Javascript library to see if it fixes it. It still has the same issues, still only on Safari. After a bit of research I saw it discussed on StackOverflow as a Safari bug.

Codepen example

jQuery(function($){
var iconsHoverIn = function() {
    TweenMax.to($(this).find('.iconBG'), 0.5, {
        rotationY: 180, 
        opacity: 0
        }
    );
    TweenMax.to($(this).find('.hoverImage'), 0.5, {
        rotationY: '-180', 
        opacity: 1
        }
    );
}
var iconsHoverOut = function() {
    TweenMax.to($(this).find('.iconBG'), 0.5, {
        rotationY: 0, 
        opacity: 1
        }
    );
    TweenMax.to($(this).find('.hoverImage'), 0.5, {
        rotationY: 0, 
        opacity: 0
        }
    );
}

$('.iconBlock').hover(iconsHoverIn, iconsHoverOut);

});

The bug is: while doing the transition, half of the element seems to transition differently than the other half. It shows a line in the middle, like if the element was made of paper and was bending in half.

Is there any way around it? I presented a few animations to the client, but this animation (rotateY) was the unanimous selection.

Note: I am somewhat new to Javascript and Greensock. You may notice better ways to do what I did. I wouldn't mind suggestions on improving it, but what I am really after is a solution to the bug/glitch.


Solution

  • As the solution you posted in your question itself suggests, adding a translateZ (which in GSAP terms just means z) to either .iconBG element or .hoverImage element should solve your problem.

    Here is the forked codepen of your demo and the code is as belows:

    JavaScript:

    var iconBlocks = $('.iconBlock');
    var iconBGs = iconBlocks.find('.iconBG');
    var hoverImages = iconBlocks.find('.hoverImage');
    var animDuration = 0.4;
    var animEase = Power2.easeOut;
    var numIcons = iconBlocks.length;
    var timelines = [];
    var timeline = null;
    for (var i = 0; i < numIcons; i += 1) {
      timeline = new TimelineMax({ paused: true });
      timeline.fromTo(iconBGs[i], animDuration, { z: 0, rotationY: 0, autoAlpha: 1 }, { rotationY: 180, autoAlpha: 0, ease: animEase }, 0);
      timeline.fromTo(hoverImages[i], animDuration, { z: 100, rotationY: 180, autoAlpha: 0 }, { rotationY: 0, autoAlpha: 1, ease: animEase }, 0);
      timelines[i] = timeline;
    }
    iconBlocks.hover(function() { timelines[$(this).index()].play(); }, function() { timelines[$(this).index()].reverse(); });
    

    And yes, I have changed things a bit. Personal preference totally, no right or wrong ways here. Let me know if this helps.