sam sexton
sam sexton

Reputation: 193

How to animate a car's wheels based on a moving and stopping car using CSS?

I'm trying to animate a car using CSS. I've managed to animate the wheels and the car.

The car moves in and stops and then moves off. this animation loops.

Now, I need to stop the wheels as well when then car stops. But I can't seem to achieve that.

This is what I have so far:

@keyframes wheel{
 0%{
   transform: rotate(0deg)
  }
  
    35% {
    transform: rotate(-90deg)
  }
  36%,
  56% {
    transform: rotate(-180deg)
  }
  
 100%{
   transform: rotate(-359deg)
  }
}

@keyframes moving {
  0% {
    right: -80em;
    animation-timing-function: ease-out;
  }
  35% {
    right: 0;
  }
  36%,
  56% {
    right: 0;
    animation-timing-function: ease-in;
  }
  100% {
    right: 120%;
  }
}

@keyframes stableWheel {
  from {transform: translateY(-.0em);}
  to {transform: translateY(-.0em);}
}


.car{
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 0 auto;
  position: relative;
  width: 600px;
  height:271px;
  overflow:hidden;
    animation: moving 10s linear -2s infinite;
}
.carbody{
  animation: carmove 3.1s infinite linear;
  background: url('https://i.sstatic.net/xWNOG.png') 0 0;
  background-size: cover;
  height: 271px;
  position: relative; 
  width: 600px;
  z-index: 125;
}



.weel{

  animation: wheel 0.7s infinite linear;
  background: url('https://i.sstatic.net/0Osjx.png') 0 0;
  height: 85px;
  position: absolute;
  top: 67%;
  width: 85px;
  z-index: 200;
}
.weel1{left: 85px;}
.weel2{left: 454px;}

/*animations*/
@keyframes carmove{
  0%{transform: translateY(0px);}
  25%{transform: translateY(1px)}
  29%{transform: translateY(2px)}
  33%{transform: translateY(3px)}
  47%{transform: translateY(0px)}
  58%{transform: translateY(1px)}
  62%{transform: translateY(2px)}
  66%{transform: translateY(3px)}
  75%{transform: translateY(1px)}
  100%{transform: translateY(0px)}
}




body {
  -webkit-animation: color-fade 10s infinite;
  -moz-animation: color-fade 10s infinite;
  animation: color-fade 10s infinite;
}

@-webkit-keyframes color-fade {
  0% { background: #9a5342; }
  25% { background: #fffc0c; }
  50% { background: #e46d00; }
  75% { background: #ff3506; }
  100% { background: #9a5342; }
}


.stopedWeel{
     animation: stableWheel .2s linear infinite alternate;
  
}
<div class="car">
  <div class="carbody"></div>
  <div class="weel weel1"></div>
  <div class="weel weel2"></div>
</div>

The wheels animation is this:

@keyframes wheel{
     0%{
       transform: rotate(0deg)
      }

        35% {
        transform: rotate(-90deg)
      }
      36%,
      56% {
        transform: rotate(-180deg)
      }

     100%{
       transform: rotate(-359deg)
      }
    }

if you run my code, the wheels are all jittery and lagging.

Could someone please advice on this?

Upvotes: 10

Views: 4725

Answers (3)

Temani Afif
Temani Afif

Reputation: 272901

To make it easier, use the same duration for both animation then increase the angle of rotation to control the wheel. Simply make sure you get back to n*360deg at then end (not mandatory in this case since there is no cycle in the car movement)

I also optimized your code to use percentage value so you can easily control the whole car by simply adjusting the width of the main element:

.car{
  margin: 0 auto;
  position: relative;
  width: 400px;
  animation: moving 10s linear -2s infinite;
}
.car:before {
  content:"";
  display:block;
  animation: carmove 3.1s infinite linear;
  background: url('https://i.sstatic.net/xWNOG.png') center/cover;
  padding-top:45.25%;
}

.weel{
  animation: wheel 10s infinite -2s linear;
  background: url('https://i.sstatic.net/0Osjx.png') center/cover;
  position: absolute;
  bottom:0.8%;
  width: 14.15%;
}
.weel:before {
   content:"";
   display:block;
   padding-top:100%;
}
.weel1{left: 14.5%;}
.weel2{right: 10%;}

/*animations*/
@keyframes carmove{
  0%{transform: translateY(0px);}
  25%{transform: translateY(1px)}
  29%{transform: translateY(2px)}
  33%{transform: translateY(3px)}
  47%{transform: translateY(0px)}
  58%{transform: translateY(1px)}
  62%{transform: translateY(2px)}
  66%{transform: translateY(3px)}
  75%{transform: translateY(1px)}
  100%{transform: translateY(0px)}
}

@keyframes wheel{
 0%{
   transform: rotate(0deg)
  }
  35% {
    transform: rotate(-920deg)
  }
  36%,
  56% {
    transform: rotate(-920deg)
  }
 100%{
   transform: rotate(-1440deg)
  }
}

@keyframes moving {
  0% {
    right: -80em;
    animation-timing-function: ease-out;
  }
  35% {
    right: 0;
  }
  36%,
  56% {
    right: 0;
    animation-timing-function: ease-in;
  }
  100% {
    right: 120%;
  }
}

body {
  overflow:hidden;
}
<div class="car">
  <div class="weel weel1"></div>
  <div class="weel weel2"></div>
</div>

And a smaller car:

.car{
  margin: 0 auto;
  position: relative;
  width: 150px;
  animation: moving 10s linear -2s infinite;
}
.car:before {
  content:"";
  display:block;
  animation: carmove 3.1s infinite linear;
  background: url('https://i.sstatic.net/xWNOG.png') center/cover;
  padding-top:45.25%;
}

.weel{
  animation: wheel 10s infinite -2s linear;
  background: url('https://i.sstatic.net/0Osjx.png') center/cover;
  position: absolute;
  bottom:0.8%;
  width: 14.15%;
}
.weel:before {
   content:"";
   display:block;
   padding-top:100%;
}
.weel1{left: 14.5%;}
.weel2{right: 10%;}

/*animations*/
@keyframes carmove{
  0%{transform: translateY(0px);}
  25%{transform: translateY(1px)}
  29%{transform: translateY(2px)}
  33%{transform: translateY(3px)}
  47%{transform: translateY(0px)}
  58%{transform: translateY(1px)}
  62%{transform: translateY(2px)}
  66%{transform: translateY(3px)}
  75%{transform: translateY(1px)}
  100%{transform: translateY(0px)}
}

@keyframes wheel{
 0%{
   transform: rotate(0deg)
  }
  35% {
    transform: rotate(-920deg)
  }
  36%,
  56% {
    transform: rotate(-920deg)
  }
 100%{
   transform: rotate(-1440deg)
  }
}

@keyframes moving {
  0% {
    right: -80em;
    animation-timing-function: ease-out;
  }
  35% {
    right: 0;
  }
  36%,
  56% {
    right: 0;
    animation-timing-function: ease-in;
  }
  100% {
    right: 120%;
  }
}

body {
  overflow:hidden;
}
<div class="car">
  <div class="weel weel1"></div>
  <div class="weel weel2"></div>
</div>

Upvotes: 16

Alexandr_TT
Alexandr_TT

Reputation: 14545

SVG Animation

Scenario

  1. The car appears on the right.
    Wheels spin

  2. Car stop in the middle of the road.
    Wheels do not spin

  3. The car rides again.
    Wheels spin

  4. Repetition of the whole cycle

Why did I write this primitive algorithm? Only in order to clearly follow it in the order of launching parallel and sequential animations.

Unlike CSS animations in SVG you can do without painstaking timing calculations.. And as it is written in the scenario so, and implement the start, stop animations

For example:

  • A pause follows after the end of the movement on the first leg

begin="an_move1.end"

  • Movement on the second section of the path will begin after pause

begin="an_pause.end"

See the code comments for more explanations.

body {
  -webkit-animation: color-fade 10s infinite;
  -moz-animation: color-fade 10s infinite;
  animation: color-fade 10s infinite;
}

@-webkit-keyframes color-fade {
  0% { background: #9a5342; }
  25% { background: #fffc0c; }
  50% { background: #e46d00; }
  75% { background: #ff3506; }
  100% { background: #9a5342; }
}

.container {
width:100%;
height:100%;
}
<div class="container">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
       width="1200" height="600" viewBox="0 0 600 800" preserveAspectRatio="xMinYMin meet">  
  <!-- Car -->
<g id="car" transform="translate(-2400,0)">
<image xlink:href="https://i.sstatic.net/xWNOG.png" width="100%" height="100%" />

 <g id="wheel_left" transform=" translate(85,430) scale(0.145)" >
   <image xlink:href="https://i.sstatic.net/0Osjx.png" width="100%" height="100%" >
     <!-- Left wheel rotation animation -->
 <animateTransform
     id="an_left"
	 attributeName="transform"
	 type="rotate"
	 begin="0s;6s;16s;26s;36s;46s;56s"
	 end="an_pause.begin"
	 values="
	 0 300 400;
	-360 300 400"
	 dur="1s"
	 repeatCount="indefinite"
 />
 </image>
 </g>  
     
 <g id="wheel_right" transform=" translate(455,430) scale(0.145)" >
 <image xlink:href="https://i.sstatic.net/0Osjx.png" width="100%" height="100%" > 
     <!-- Right wheel rotation animation -->
    <animateTransform
	  id="an_right"
	  attributeName="transform"
	  type="rotate"
	  begin="0s;6s;16s;26s;36s;46s;56s;66s;76s"
	  end="an_pause.begin"
	  values="
	   0 300 400;
	-360 300 400"
	  dur="1s"
	  repeatCount="indefinite"
	/>
 </image>
 </g>
</g>   
<!-- Animation of a car moving to a stop -->
 <animateTransform
   id="an_move1"
   xlink:href="#car"
   attributeName="transform"
   type="translate"
   begin="0s;an_move2.end"
   values="2400;800"
   dur="4s"
   fill="freeze"
   repeatCount="1"
 />  
 <!-- Car  move  pause  -->
 <animateTransform
   id="an_pause"
   xlink:href="#car"
   attributeName="transform"
   type="translate"
   begin="an_move1.end"
   values="800"
   dur="2s"
   fill="freeze"
   repeatCount="1"
 /> 
 <!-- Animation of a car moving after a stop -->
  <animateTransform
   id="an_move2"
   xlink:href="#car"
   attributeName="transform"
   type="translate"
   begin="an_pause.end"
   values="800;-600"
   dur="4s"
   fill="freeze"
   repeatCount="1"
 /> 

</svg>	 
</div>

Upvotes: 4

VSM
VSM

Reputation: 1785

At the middle of the view screen both car and wheel animations should be stopped few seconds. So wheel animation should be same as car's animation.

.car{
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  margin: 0 auto;
  position: relative;
  width: 600px;
  height:271px;
  overflow:hidden;
  animation: moving 10s linear -2s infinite;
}

Updated wheel styles should be looked like below.

.weel{
  /*animation: wheel 0.7s infinite linear;*/
  animation: wheel 10s linear -2s infinite;

  background: url('https://i.sstatic.net/0Osjx.png') 0 0;
  height: 85px;
  position: absolute;
  top: 67%;
  width: 85px;
  z-index: 200;
}

If you run the code now you can see wheel and car animate works simultaneously. But there you can find a difference between car speed and wheel speed and wheel should be stopped until car body moves again. For fix that speed and wheel issues, you need to increase keyframe values while keep middle two keyframe values equal.

@keyframes wheel{
0%{
   transform: rotate(0deg)
  }

    35% {
    transform: rotate(-500deg)
  }
  36%,
  56% {
    transform: rotate(-500deg)
  }

 100%{
   transform: rotate(-1000deg)
  }
}

This Js Fiddle link shows the live animation.

Upvotes: 1

Related Questions