Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jerking animation on css3 spinner

I found one attractive spinner(CSS3, SCSS): http://codepen.io/weaintplastic/pen/qEMZbx.

@for $i from 1 through 6 {
    @keyframes preload-show-#{$i}{
        from{
            transform: rotateZ(60* $i + deg) rotateY(-90deg) rotateX(0deg);
            border-left-color: #9c2f2f;
        }
    }
    @keyframes preload-hide-#{$i}{
        to{
            transform: rotateZ(60* $i + deg) rotateY(-90deg) rotateX(0deg);
            border-left-color: #9c2f2f;
        }
    }

    @keyframes preload-cycle-#{$i}{

        $startIndex: $i*5;
        $reverseIndex: (80 - $i*5);

        #{$startIndex * 1%}{
            transform: rotateZ(60* $i + deg) rotateY(90deg) rotateX(0deg);
            border-left-color: #9c2f2f;
        }
        #{$startIndex + 5%},
        #{$reverseIndex * 1%}{
            transform: rotateZ(60* $i + deg) rotateY(0) rotateX(0deg);
            border-left-color: #f7484e;
        }

        #{$reverseIndex + 5%},
        100%{
            transform: rotateZ(60* $i + deg) rotateY(90deg) rotateX(0deg);
            border-left-color: #9c2f2f;
        }
    }
}

@keyframes preload-flip{
    0%{
        transform: rotateY(0deg) rotateZ(-60deg);
    }
    100%{
        transform: rotateY(360deg) rotateZ(-60deg);
    }
}

body{
  background: #efefef;
}

.preloader{
  position: absolute;
  top: 50%;
  left: 50%;
    font-size: 20px;
    display: block;
    width: 3.75em;
    height: 4.25em;
    margin-left: -1.875em;
  margin-top: -2.125em;
    transform-origin: center center;
    transform: rotateY(180deg) rotateZ(-60deg);

    .slice{
        border-top: 1.125em solid transparent;
        border-right: none;
        border-bottom: 1em solid transparent;
        border-left: 1.875em solid #f7484e;
        position: absolute;
        top: 0px;
        left: 50%;
        transform-origin: left bottom;
        border-radius: 3px 3px 0 0;
    }

    @for $i from 1 through 6 {
      .slice:nth-child(#{$i}) { 
        transform: rotateZ(60* $i + deg) rotateY(0deg) rotateX(0);
        animation: .15s linear .9 - $i*.08s preload-hide-#{$i} both 1;
      }
    }


    &.loading{
        animation: 2s preload-flip steps(2) infinite both;
        @for $i from 1 through 6 {
          .slice:nth-child(#{$i}) { 
            transform: rotateZ(60* $i + deg) rotateY(90deg) rotateX(0);
            animation: 2s preload-cycle-#{$i} linear infinite both;
          }
        }
    }

}
<div class="preloader loading">
  <span class="slice"></span>
  <span class="slice"></span>
  <span class="slice"></span>
  <span class="slice"></span>
  <span class="slice"></span>
  <span class="slice"></span>
</div>

But it has the jerking moment(glitch) in the middle of animation: bottom part of hexagon moves to right on one or two pixels.

I took video of this moment: youtu.be/_TwDuxME8wc.

I tried to repair it on my own, but I haven't enough skills. Could you prompt how it can be fixed? Thanks!

like image 434
makrusak Avatar asked Apr 21 '15 09:04

makrusak


3 Answers

You use a lot of em measurements, which results in a lot of decimal pixel values. It's important that you only have integer values to avoid these glitches.

If you take @Nick Barlett's solution and change the font-size of .preloader from 20px to 24px you will get rid of the decimal values. See this pen: http://codepen.io/pstenstrm/pen/mJJpvP

This will of course make the loader bigger too, so you might want to change the em values to px.

like image 143
pstenstrm Avatar answered Nov 05 '22 03:11

pstenstrm


Change the 100% state on the preload-flip to have rotateZ(64deg)

@keyframes preload-flip{
    0%{
        transform: rotateY(0deg) rotateZ(-60deg);
    }
    100%{
        transform: rotateY(360deg) rotateZ(-64deg);
    }
}

There seems to be a bigger issue overall with the angles, though, as the pen is slightly askew to begin with.

like image 31
Nick Bartlett Avatar answered Nov 05 '22 02:11

Nick Bartlett


@pstenstrm's solution brilliantly resolves the glitch problem, +1.

It introduces another problem, though:

In Firefox (only?), there is an ugly jagged border in the top left triangle.

To solve it, just add a trasparent outline to the triangles:

.slice{
  outline: 1px solid transparent;
}

Check out the demo to see the final result:

Running demo

like image 1
Andrea Ligios Avatar answered Nov 05 '22 02:11

Andrea Ligios