抹桥的博客
Language
Home
Archive
About
GitHub
Language
主题色
250
862 words
4 minutes
Creating a CSS3 Character Race Animation

Recently, a mobile project at my company required an animation. The animation depicts a person running on a track. To achieve better performance on mobile devices, we opted to implement the entire animation using CSS3. As this was my first time tackling such a task, I encountered numerous issues, which I’ve documented here.

Here’s what the final animation looks like: All

Analysis#

Upon receiving the design, I first analyzed it. The animation can be broken down into four main parts:

  • The running person
  • The moving road
  • The left road signs
  • The income signs

The Runner#

The runner was straightforward to implement. By using a sprite sheet of a person running, person and then changing its background-position frame by frame, it was quite simple.

.person {
    width: 62px;
    height: 110px;
    background: url(../imgs/plan/person1.png) -7px 0 no-repeat;
    background-size: auto 110px;
    animation: run .5s infinite;			// Remember to add vendor prefixes for various browsers, especially -webkit-. I'll omit them here for brevity.
    position: absolute;
    top: 40%;
    left: 110*.84px;
}
@keyframes run {
    0% {
        background-position: -7px 0
    }
    25% {
        background-position: -79px 0
    }
    50% {
        background-position: -150px 0
    }
    75% {
        background-position: -216px 0
    }
    100% {
        background-position: -283px 0
    }
}

However, the runner initially looked like this: person-wrong It was terrible. Upon analyzing the cause, I realized that keyframes have a default transition. This meant my background-position was linearly interpolating from -7 to -283, which was certainly not the desired outcome. I suspected this was an issue with the animation timing function, so I looked up the possible values for animation-timing-function:

linear: Linear transition. Equivalent to Bezier curve (0.0, 0.0, 1.0, 1.0) ease: Smooth transition. Equivalent to Bezier curve (0.25, 0.1, 0.25, 1.0) ease-in: Starts slow, then speeds up. Equivalent to Bezier curve (0.42, 0, 1.0, 1.0) ease-out: Starts fast, then slows down. Equivalent to Bezier curve (0, 0, 0.58, 1.0) ease-in-out: Starts slow, speeds up, then slows down. Equivalent to Bezier curve (0.42, 0, 0.58, 1.0) step-start: Equivalent to steps(1, start) step-end: Equivalent to steps(1, end) steps([, [ start | end ] ]?): A stepping function that accepts two parameters. The first parameter must be a positive integer, specifying the number of steps in the function. The second parameter can be start or end, specifying the point in time when each step’s value changes. The second parameter is optional and defaults to end. cubic-bezier(, , , ): A specific Bezier curve type, where the 4 values must be within the [0, 1] range.

The step property was exactly what we needed, allowing it to jump directly from one state to another instead of transitioning. Adding this property to the .person class above solved the issue:

animation-timing-function: step-start;

person-run With that, the runner’s animation was resolved.

The Road#

Initially, I couldn’t think of a good approach for the road. My first thought was to cut a large section, create two images, and then alternate their appearance. However, this would result in very large images, consuming network resources and feeling like a clumsy method. After analyzing the track, I came up with a better idea. runway By extracting the smallest repeating segment of the track, tiling it vertically, and then moving its background-position by half the image’s height each time, the effect could be achieved. runway-run This also solved the road animation.

The Left Road Sign#

This was very simple. I just set its absolute position and then changed its top value. It’s important to note that the last sign needed to stop in the middle. Adding this property achieved that:

animation-fill-mode: forwards;

The animation-fill-mode property specifies how an animation’s effects are applied before or after it plays. Values none: Does not change the default behavior. forwards: When the animation completes, it retains the computed values of the properties for the last keyframe. backwards: During the period defined by animation-delay, the starting property values (defined in the first keyframe) are applied before the animation begins. both: Both forwards and backwards fill modes are applied.

The Income Sign#

Similar to the left road sign, this was very simple. It merely involved appearing and disappearing.

Combination#

After resolving the four parts of the animation, the next step was to combine them. process The image above shows the flow chart for the first road sign’s process from appearing on screen to disappearing. For the other two road signs, their processes simply required delaying the animation by the corresponding time intervals. There was also an issue of making the runner and the road stop at a specific point. This didn’t seem achievable with CSS3 alone, so I opted for a fallback: controlling it with JavaScript. By setting its webkit-animation-play-state property to paused and running, I could make it stop and then resume movement. Finally, a pop-up needed to appear after the animation completed. This was achieved by detecting the animationEnd event. Here’s the implementation:

/* From Modernizr */
function whichAnimationEvent(){
    var t;
    var el = document.createElement('fakeelement');
    var animations = {
      'animation':'animationend',
      'OAnimation':'oAnimationEnd',
      'MozAnimation':'animationend',
      'WebkitAnimation':'webkitAnimationEnd'
    }

    for(t in animations){
        if( el.style[t] !== undefined ){
            return animations[t];
        }
    }
}

/* Listen for a transition! */
var transitionEvent = whichAnimationEvent();
whichAnimationEvent && e.addEventListener(whichAnimationEvent, function() {
	//doSomething
});

/*
	The "whichTransitionEvent" can be swapped for "animation" instead of "transition" texts, as can the usage :)
*/

Result#

Here is the final completed effect. Click here to see the animation

This article was published on May 21, 2015 and last updated on May 21, 2015, 3791 days ago. The content may be outdated.

Creating a CSS3 Character Race Animation
https://blog.kisnows.com/en-US/2015/05/21/income-plan-animation/
Author
Kisnows
Published at
2015-05-21
License
CC BY-NC-ND 4.0