मैं CSS "रोलर कोस्टर" एनीमेशन में एक लाइन कैसे वक्र कर सकता हूं?


15

मैं CSS के साथ एक रोलर कोस्टर स्टाइल एनीमेशन बनाने की कोशिश कर रहा हूं।

मैं जानना चाहता हूं कि जब लूप चरण में होता है तो "कोस्टर" को कैसे वक्र किया जाता है।

मैं एक सभी सीएसएस समाधान के लिए खोज रहा हूँ, लेकिन अगर वहाँ जावास्क्रिप्ट की जरूरत है कि मैं इसके साथ ठीक हूँ।

मेरा कोड अब तक:

#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>

जवाबों:


12

आप विचार कर सकते हैं border-radius। यहां एक बुनियादी उदाहरण है जिसे आप सुधार सकते हैं

एक और पागल विचार जहां आप एक पारदर्शी घुमावदार रास्ते के पीछे एक आयताकार आकार को चेतन कर सकते हैं:

कोड के साथ और पारदर्शिता के साथ एक अनुकूलित संस्करण (इसके लिए विचार करेगा mask)

कम पिक्सेल मूल्यों और सीएसएस चर के साथ एक और संस्करण जहां आप आसानी से सब कुछ समायोजित कर सकते हैं।

स्निपेट को पूरे पृष्ठ पर चलाएं और सभी कोस्टरों के साथ मज़े करें!

.box {
  --w:400px; /* Total width of the coaster */
  --h:180px; /* Height of the coaster */
  --b:90px;  /* width of the small bar */
  --t:15px;  /* height of the small bar */
  --c:blue;  /* Color of the small bar */
  
  width:var(--w);
  height:var(--h);
}

.box > div {
  height: 100%;
  position:relative;
  width: calc(50% + var(--h)/2 + var(--b)/2);
  border-radius: 0 1000px 1000px 0;
  animation: hide 3s infinite linear alternate;
  -webkit-mask:
    linear-gradient(#fff,#fff) top left   /calc(100% - var(--h)/2) var(--t),
    linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
    radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
   -webkit-mask-repeat:no-repeat; 
   mask:
    linear-gradient(#fff,#fff) top left   /calc(100% - var(--h)/2) var(--t),
    linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
    radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
   mask-repeat:no-repeat;
}
.box > div:last-child {
  margin-top:calc(-1*var(--h));
  margin-left:auto;
  transform: scaleX(-1);
  animation-direction: alternate-reverse;
}

.box > div:before {
  content: "";
  position: absolute;
  width: var(--b);
  height: 50%;
  background: var(--c);
  bottom: -25%;
  animation: loop 3s infinite linear alternate;
  transform-origin: 50% -50%;
}

.box > div:last-child:before {
  animation-direction: alternate-reverse;
}

@keyframes loop {
  15% {
    transform: translateX(calc(var(--w)/2)) rotate(0deg);
  }
  40% {
    transform: translateX(calc(var(--w)/2)) rotate(-180deg);
  }
  50%,100% {
    transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(-180deg);
  }
}

@keyframes hide {
  50% {
    visibility: visible;
  }
  50.1%,100% {
    visibility: hidden;
  }
}

body {
  background:linear-gradient(to right,yellow,gray);
}
<div class="box">
<div></div><div></div>
</div>

<div class="box" style="--w:500px;--h:80px;--b:50px;--c:red;--t:5px">
<div></div><div></div>
</div>

<div class="box" style="--w:90vw;--h:200px;--b:100px;--c:purple;--t:20px">
<div></div><div></div>
</div>


चाल को समझने के लिए, आइए मास्क को हटाएं और इसे एक साधारण ढाल से बदलें और छिपाने के एनीमेशन को हटा दें:

ग्रेडिएंट द्वारा बनाया गया रास्ता हमारा मुखौटा है और हम केवल उस हिस्से को देखेंगे। फिर हम पथ का पालन करने के लिए अपनी आयत बनाते हैं और लूप प्रभाव बनाने के लिए चाल दो सममित तत्व रखते हैं। छिपाने एनीमेशन हमें उनमें से केवल एक को देखने के लिए अनुमति देगा और सही ओवरलैप एक सतत एनीमेशन पैदा करेगा।


यदि आप कोस्टर के लिए एक सर्कल चाहते हैं तो यहां एक संस्करण है

.box {
  --w:400px; /* Total width of the coaster */
  --h:180px; /* Height of the coaster */
  --b:90px;  /* width of the small bar */
  --t:15px;  /* height of the small bar */
  --c:blue;  /* Color of the small bar */
  
  width:var(--w);
  height:var(--h);
}

.box > div {
  height: 100%;
  position:relative;
  width: calc(50% + var(--h)/2);
  border-radius: 0 1000px 1000px 0;
  animation: hide 3s infinite linear alternate;
  -webkit-mask:
    radial-gradient(farthest-side at bottom right,transparent calc(100% - var(--t)),#fff 0 100%,transparent 100%) top 0 right calc(var(--h)/2)/calc(var(--h)/2) 50%,
    linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
    radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
   -webkit-mask-repeat:no-repeat; 
   mask:
    radial-gradient(farthest-side at bottom right,transparent calc(100% - var(--t)),#fff 0 100%,transparent 100%) top 0 right calc(var(--h)/2)/calc(var(--h)/2) 50%,
    linear-gradient(#fff,#fff) bottom left/calc(100% - var(--h)/2) var(--t),
    radial-gradient(farthest-side at left,transparent calc(100% - var(--t)),#fff 0) right/calc(var(--h)/2) 100%;
   mask-repeat:no-repeat;
}
.box > div:last-child {
  margin-top:calc(-1*var(--h));
  margin-left:auto;
  transform: scaleX(-1);
  animation-direction: alternate-reverse;
}

.box > div:before {
  content: "";
  position: absolute;
  width: var(--b);
  height: 50%;
  background: var(--c);
  bottom: -25%;
  animation: loop 3s infinite linear alternate;
  transform-origin: 50% -50%;
}

.box > div:last-child:before {
  animation-direction: alternate-reverse;
}

@keyframes loop {
  15% {
    transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(0deg);
  }
  50%,100% {
    transform: translateX(calc(var(--w)/2 - var(--b)/2)) rotate(-180deg);
  }
}

@keyframes hide {
  50% {
    visibility: visible;
  }
  50.1%,100% {
    visibility: hidden;
  }
}

body {
  background:linear-gradient(to right,yellow,gray);
}
<div class="box">
<div></div><div></div>
</div>

<div class="box" style="--w:500px;--h:80px;--b:50px;--c:red;--t:5px">
<div></div><div></div>
</div>

<div class="box" style="--w:90vw;--h:200px;--b:100px;--c:purple;--t:20px">
<div></div><div></div>
</div>


4

आप सभी को धन्यवाद, और विशेष रूप से तमानी अफीफ को आपकी प्रेरणा के लिए :]

मैंने अंततः आपके उत्तर का उपयोग करते border-radiusहुए तत्वों को छिपा दिया, और तत्वों को छिपाकर मुझे लगता है कि मैंने एनीमेशन के लिए एक महान समाधान बनाया है।

* {
  box-sizing: border-box;
}

#container {
  width: 100px;
  height: 100px;
  margin-top: 50px;
  position: relative;
  animation: 5s infinite loop linear;
}

#coasterLine {
  height: 10px;
  background: lightblue;
  position: absolute;
  z-index: 20;
  bottom: 0;
  animation: 5s infinite c-line linear;
}

#coasterRound {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  border: solid transparent 10px;
  border-bottom: solid lightblue 10px;
  position: relative;
  animation: 5s infinite c-round linear;
}

#whiteScreen {
  width: 100%;
  background: white;
  position: absolute;
  z-index: 10;
  top: 0;
  animation: 5s infinite white-screen linear;
}

@keyframes loop {
  0% {
    margin-left: -200px;
  }
  38%,
  43% {
    margin-left: calc(50% - 50px);
  }
  58%,
  63% {
    margin-left: calc(50% - 50px);
  }
  100% {
    margin-left: 100%;
  }
}

@keyframes c-round {
  0%,
  43% {
    transform: rotate(-45deg);
  }
  58%,
  100% {
    transform: rotate(-315deg);
  }
}

@keyframes c-line {
  0%,
  38% {
    left: 0;
    width: 60px;
  }
  43% {
    left: 50px;
    width: 0;
  }
  58% {
    left: 40px;
    width: 0;
  }
  63%,
  100% {
    left: 40px;
    width: 60px;
  }
}

@keyframes white-screen {
  0%,
  38% {
    height: 100%;
    transform: rotate(0deg);
  }
  43% {
    height: 50%;
    transform: rotate(0deg);
  }
  44%,
  57% {
    height: 0;
    transform: rotate(0deg);
  }
  58% {
    height: 50%;
    transform: rotate(180deg);
  }
  63%,
  100% {
    height: 100%;
    transform: rotate(180deg);
  }
}
<div id="container">
  <div id="coasterLine"></div>
  <div id="coasterRound"></div>
  <div id="whiteScreen"></div>
</div>

यह बहुत अच्छा रहा!


0

वास्तव में प्राकृतिक नहीं लग रहा है लेकिन border-radiusशुरू करने का एक अच्छा तरीका है:

#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

मुझे लगता है कि नीचे का दृष्टिकोण कम या ज्यादा ध्वनि वाला है (हालांकि मैं इस बात से सहमत होने वाला पहला व्यक्ति हूं कि इसका जल्दबाजी में लागू होना सही नहीं है)।

रोलरकोस्टर के बजाय द्वारा एक प्रतिनिधित्व किया जा रहा <div>यह का प्रतिनिधित्व करती है border-bottomएक की <div>

उस सीमा के अपने एक साथ एनीमेशन में, border-bottom-left-radiusऔर समय के साथ border-bottom-left-radiusझुकना 50%, वापस झुकने से पहले 0

काम करने का उदाहरण:

#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>

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.