web-dev-qa-db-fra.com

Comment puis-je courber une ligne dans une animation CSS "roller coaster"?

J'essaie de créer une animation de style roller coaster avec CSS.

Je veux savoir comment courber le "coaster" quand il est dans la phase de boucle.

Je recherche une solution tout CSS mais s'il y a un besoin d'un peu de JavaScript, je suis d'accord avec ça.

mon code jusqu'à présent:

#container {
  width: 200px;
  height: 300px;
  margin-top: 50px;
  position: relative;
  animation: 10s infinite loop;
  animation-timing-function: linear;
}

#coaster {
  width: 100px;
  height: 10px;
  background: lightblue;
  position: absolute;
  bottom: 0;
  left: 1px;
  right: 1px;
  margin: 0 auto;
}

@keyframes loop {
  from {
    margin-left: -200px;
  }
  30% {
    margin-left: calc(50% - 75px);
    transform: rotate(0deg);
  }
  60% {
    margin-left: calc(50% - 125px);
    transform: rotate(-360deg);
  }
  to {
    transform: rotate(-360deg);
    margin-left: 100%;
  }
}
<div id="container">
  <div id="coaster"></div>
</div>
15
Matan Sanbira

Je pense que l'approche ci-dessous est plus ou moins saine (même si je serais le premier à convenir que cette mise en œuvre précipitée n'est pas parfaite).

Au lieu que les montagnes russes soient représentées par un <div> il est représenté par le border-bottom d'un <div>.

Dans l'animation simultanée de cette frontière, le border-bottom-left-radius et le border-bottom-left-radius pliez en 50% au fil du temps, avant de se replier sur 0.

Exemple de travail:

#container {
  width: 180px;
  height: 180px;
  position: relative;
  animation: 10s loop-container linear infinite;
}

#coaster {
  width: 180px;
  height: 180px;
  border-bottom: 10px solid lightblue;
  position: absolute;
  bottom: 0;
  left: 1px;
  right: 1px;
  margin: 0 auto;
  animation: 10s loop-coaster linear infinite;
}

@keyframes loop-container {
  0% {
    margin-left: -200px;
  }
  30% {
    margin-left: calc(50% - 75px);
    transform: rotate(0deg);
  }
  60% {
    margin-left: calc(50% - 125px);
    transform: rotate(-360deg);
  }
  100% {
    transform: rotate(-360deg);
    margin-left: 100%;
  }
}

@keyframes loop-coaster {
  30% {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }
  31% {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 25%;
  }
  35%, 55% {
    border-bottom-left-radius: 50%;
    border-bottom-right-radius: 50%;
  }
  59% {
    border-bottom-left-radius: 25%;
    border-bottom-right-radius: 0;
  }
  60% {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }
}
<div id="container">
  <div id="coaster"></div>
</div>
0
Rounin

Cela n'a pas l'air vraiment naturel mais border-radius semble être une bonne façon de commencer:

#container {
  width: 200px;
  height: 300px;
  margin-top: 50px;
  position: relative;
  animation: 10s infinite loop;
  animation-timing-function: linear;
}

#coaster {
  width: 100px;
  height: 10px;
  background: lightblue;
  position: absolute;
  bottom: 0;
  left: 1px;
  right: 1px;
  margin: 0 auto;
  animation: 10s infinite coasterAnimation;
}

@keyframes loop {
  from {
    margin-left: -200px;
  }

  30% {
    margin-left: calc(50% - 75px);
    transform: rotate(0deg);
  }

  60% {
    margin-left: calc(50% - 125px);
    transform: rotate(-360deg);
  }

  to {
    transform: rotate(-360deg);
    margin-left: 100%;
  }
}

@keyframes coasterAnimation {

  29% {
    border-radius: 0;
  }

  30% {
    border-radius: 0 0 50% 50%;
  }

  59% {
    border-radius: 0 0 50% 50%;
  }

  60% {
    border-radius: 0;
  }

  70% {
    border-radius: 0;
  }
}
<div id="container">
  <div id="coaster"></div>
</div>
0
johannchopin