Animnate Car Landing Page Using Html Css And Javascript
Hello friends, welcome to this wonderful blog post today. Today we have created a great project for you which is a landing page. This landing page is Tesla Roadster landing page. This landing page is animated and you can use it on any device. We have used HTML CSS and JavaScript to create this landing page. If you do not have any knowledge of HTML CSS or JavaScript, you can still use this project. This is a completely beginner-friendly project. We have created the UI of this animated landing page in a very good way, which looks very amazing.
Tesla Roadster Html Code
Tesla hero slider
Tesla Roadster Css Code
/* Typography
-------------------------------------------------------------- */
@font-face {
font-family: "BebasNeue";
src: url("https://raw.githubusercontent.com/10clouds/codepen/tesla-hero-slider/tesla-hero-slider/src/assets/fonts/BebasNeue-Regular.otf");
}
/* Breakpoints
-------------------------------------------------------------- */
/* Media queries
-------------------------------------------------------------- */
* {
box-sizing: border-box;
}
:root {
--btn-color: white;
--car-color: white;
--bckg-height: 300px;
--shadow-opacity: 0.2;
--car-shadow-height: 300px;
}
body {
background-color: black;
overflow-x: hidden;
}
ul {
padding: 0;
list-style: none;
}
.container {
max-width: 780px;
padding: 10px;
margin: 0 auto;
}
@media only screen and (min-width:768px) {
.container {
padding: 0 20px;
}
}
@media only screen and (min-width:992px) and (max-width:1199px) {
.container {
max-width: 1000px;
}
}
@media only screen and (min-width:1200px) {
.container {
max-width: 1200px;
}
}
@media only screen and (min-width:1800px) {
.container {
max-width: 1550px;
}
}
/* Body, html
-------------------------------------------------------------- */
html {
font-size: 62.5%;
}
body {
font-size: 14px;
font-size: 1.4rem;
line-height: 22px;
line-height: 2.2rem;
font-family: "Helvetica", "Arial", sans-serif;
color: #fff;
}
@media only screen and (min-width:992px) {
body {
font-size: 16px;
font-size: 1.6rem;
line-height: 26px;
line-height: 2.6rem;
}
}
@media only screen and (min-width:1800px) {
body {
font-size: 18px;
font-size: 1.8rem;
}
}
/* Headers
-------------------------------------------------------------- */
h1 {
margin: 0;
font-size: 5.5rem;
line-height: 1;
font-family: "BebasNeue", "Helvetica", "Arial", sans-serif;
letter-spacing: 0.9px;
font-weight: 500;
}
@media only screen and (min-width:768px) {
h1 {
font-size: 7rem;
}
}
@media only screen and (min-width:1200px) {
h1 {
font-size: 8rem;
}
}
@media only screen and (min-width:1800px) {
h1 {
font-size: 9.2rem;
}
}
/* Text, Links
-------------------------------------------------------------- */
a {
text-decoration: none;
color: #fff;
}
/* Button
-------------------------------------------------------------- */
.button {
position: relative;
height: 55px;
width: 180px;
background: none;
color: #fff;
font-size: 1.4rem;
font-weight: 300;
text-align: center;
border: 0;
cursor: pointer;
}
@media only screen and (min-width:992px) {
.button {
font-size: 1.8rem;
width: 210px;
}
}
.button:focus {
outline: none;
}
.button:hover:before {
height: 100%;
opacity: 1;
}
.button:before {
position: absolute;
content: "";
left: 0;
bottom: 0;
width: 100%;
height: 0;
opacity: 0;
background-color: var(--btn-color);
transition: all 0.3s;
z-index: -1;
}
.button__border {
position: absolute;
top: 0;
left: 0;
height: 55px;
width: 180px;
border: 1px solid var(--btn-color);
transition: all 0.6s ease-in-out;
}
.button__border:after {
position: absolute;
content: "";
left: 50%;
top: 50%;
width: 150%;
height: 220%;
opacity: 0.3;
transform: translate(-50%, -50%);
background: radial-gradient(ellipse at center, var(--btn-color) 1%, transparent 80%);
z-index: -1;
transition: opacity 0.6s ease-in-out, background 0.6s linear 0.5s;
}
@media only screen and (min-width:992px) {
.button__border {
width: 210px;
}
}
.button__border--enter {
border: 1px solid transparent;
}
.button__border--enter:after {
opacity: 0;
background: transparent;
}
.button__border--exit {
border: 1px solid transparent;
}
.button__border--exit:after {
opacity: 0.2;
background: transparent;
}
/* Header
-------------------------------------------------------------- */
.tesla-header {
display: flex;
justify-content: space-between;
padding: 25px 0;
}
@media only screen and (min-width:1200px) {
.tesla-header {
padding: 50px 0 60px;
}
}
@media only screen and (min-width:1800px) {
.tesla-header {
padding: 80px 0;
}
}
.tesla-header__logo img {
height: 12.5px;
width: auto;
}
.tesla-header__nav img {
height: 20px;
width: auto;
}
/* Slide Item
-------------------------------------------------------------- */
.tesla-slide {
position: relative;
margin-top: 50px;
width: 100%;
order: 1;
/* Slide Item Img
-------------------------------------------------------------- */
/* Slide Item Img
-------------------------------------------------------------- */
}
@media only screen and (min-width:768px) {
.tesla-slide {
margin-top: 70px;
}
}
@media only screen and (min-width:1200px) {
.tesla-slide {
margin-top: 0;
width: calc(100% - 150px);
}
}
.tesla-slide__img {
position: absolute;
overflow: hidden;
transform: translateX(0) scale(1);
transition: opacity 0.8s ease-in-out 0.05s, transform 0.8s ease-in-out 0.1s;
}
@media only screen and (max-width:767px) {
.tesla-slide__img {
width: 100%;
transform: none;
overflow: initial;
}
}
@media only screen and (min-width:768px) {
.tesla-slide__img {
margin-top: 0;
top: -5%;
right: -50%;
z-index: -1;
}
}
@media only screen and (min-width:992px) {
.tesla-slide__img {
top: -35%;
right: -25%;
}
}
@media only screen and (min-width:1800px) {
.tesla-slide__img {
top: -50%;
right: -19%;
}
}
.tesla-slide__img:before {
position: absolute;
content: "";
width: calc(var(--car-shadow-height));
height: calc(var(--car-shadow-height) * 1.4);
top: 45%;
left: 60%;
transform: translate(-50%, -50%);
opacity: 0.35;
background: radial-gradient(ellipse at center, var(--car-color) 10%, transparent 75%);
transition: opacity 0.5s ease-in 0.3s;
z-index: 9;
}
@media only screen and (min-width:992px) {
.tesla-slide__img:before {
width: calc(var(--car-shadow-height) * 2);
height: calc(var(--car-shadow-height) * 1.8);
opacity: 0.4;
}
}
.tesla-slide__img-floor {
position: absolute;
left: 0;
top: 0;
transition: all 0.7s ease-in-out 0.4s;
}
.tesla-slide__img-car {
transition: opacity 0.6s ease-in-out 0.1s;
}
.tesla-slide__img--enter {
opacity: 0;
transform: translateX(-5%) scale(1.1);
}
.tesla-slide__img--enter .tesla-slide__img-floor {
opacity: 0;
}
.tesla-slide__img--enter .tesla-slide__img-car {
opacity: 0;
}
.tesla-slide__img--enter:before {
opacity: 0;
}
.animation-back .tesla-slide__img--enter {
opacity: 0;
transform: scale(0.8);
}
.tesla-slide__img--exit {
transition: opacity 0.5s ease-in-out 0.4s, transform 0.8s ease-in-out 0.3s;
opacity: 0;
transform: scale(0.9);
}
.tesla-slide__img--exit .tesla-slide__img-floor {
transition: all 0.5s ease-in-out 0.2s;
opacity: 0;
}
.tesla-slide__img--exit:before {
transition: opacity 0.5s ease-in-out;
opacity: 0;
}
.animation-back .tesla-slide__img--exit {
transition: opacity 0.5s ease-in-out 0.6s, transform 0.9s ease-in-out 0.1s;
transform: translateX(-5%) scale(1.1);
}
.animation-back .tesla-slide__img--exit .tesla-slide__img-floor {
transition: all 0.5s ease-in-out 0.2s;
opacity: 0;
}
.animation-back .tesla-slide__img--exit .tesla-slide__img-car {
transition: opacity 0.6s ease-in-out 0.5s;
opacity: 0;
}
.animation-back .tesla-slide__img--exit:before {
transition: opacity 0.5s ease-in 0.3s;
}
.tesla-slide__img img {
max-width: 100%;
min-width: 600px;
transform: translateX(-50%);
margin: -100px 0 0 55%;
}
@media only screen and (max-width:480px) {
.tesla-slide__img img {
margin: -10px 0 0 40%;
}
}
@media only screen and (min-width:768px) {
.tesla-slide__img img {
max-width: 85%;
transform: none;
margin: -40px 0 0;
}
}
@media only screen and (min-width:992px) {
.tesla-slide__img img {
min-width: 800px;
margin-top: 0;
max-width: 1300px;
}
}
@media only screen and (min-width:1800px) {
.tesla-slide__img img {
max-width: 2000px;
}
}
.tesla-slide__bckg {
position: absolute;
right: 5%;
bottom: 38%;
width: 250px;
height: calc(var(--bckg-height) / 2.2);
z-index: -1;
}
@media only screen and (max-width:480px) {
.tesla-slide__bckg {
right: 3%;
bottom: 35%;
height: calc(var(--bckg-height) / 2.5);
}
}
@media only screen and (min-width:768px) {
.tesla-slide__bckg {
width: 300px;
height: calc(var(--bckg-height) / 1.8);
bottom: 40%;
right: 0;
}
}
@media only screen and (min-width:992px) {
.tesla-slide__bckg {
width: 400px;
height: calc(var(--bckg-height) / 1.5);
right: -2%;
}
}
@media only screen and (min-width:1200px) {
.tesla-slide__bckg {
bottom: 56%;
}
}
@media only screen and (min-width:1800px) {
.tesla-slide__bckg {
height: var(--bckg-height);
width: 570px;
right: 2%;
}
}
.tesla-slide__bckg:before, .tesla-slide__bckg:after {
position: absolute;
content: "";
transition: all 0.8s ease-in-out 0.3s;
}
.tesla-slide__bckg:after {
width: calc(var(--bckg-height) * 1.2);
height: calc(var(--bckg-height) * 0.8);
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
opacity: 0.5;
background: radial-gradient(ellipse at center, var(--car-color) 25%, transparent 65%);
}
@media only screen and (min-width:768px) {
.tesla-slide__bckg:after {
width: calc(var(--bckg-height) * 2);
height: calc(var(--bckg-height) * 1.5);
}
}
@media only screen and (min-width:1800px) {
.tesla-slide__bckg:after {
width: calc(var(--bckg-height) * 3.5);
height: calc(var(--bckg-height) * 2.2);
}
}
.tesla-slide__bckg:before {
width: calc(var(--bckg-height) * 1.5);
height: calc(var(--bckg-height) * 0.7);
top: 70%;
left: -40%;
opacity: var(--shadow-opacity);
background: radial-gradient(ellipse at center, var(--car-color) 10%, transparent 65%);
}
@media only screen and (min-width:768px) {
.tesla-slide__bckg:before {
width: calc(var(--bckg-height) * 3.5);
height: var(--bckg-height);
top: 100%;
left: -80%;
}
}
@media only screen and (min-width:1800px) {
.tesla-slide__bckg:before {
width: calc(var(--bckg-height) * 4.5);
}
}
.tesla-slide__bckg-fill {
position: absolute;
top: 0;
bottom: 0;
left: 0;
height: 100%;
width: 100%;
opacity: 0.8;
background: var(--car-color);
transition: all 0.8s ease-in 0.3s, transform 0.8s ease-in-out, background 0s;
}
.tesla-slide__bckg--enter .tesla-slide__bckg-fill {
height: 0;
top: 0;
bottom: 100%;
opacity: 0.3;
transform: translateY(-20px) scale(1.1);
transition: all 0.7s ease-in 0.5s, transform 0.8s ease-in-out 0.1s, background 0s;
}
.tesla-slide__bckg--enter:before, .tesla-slide__bckg--enter:after {
opacity: 0;
}
.animation-back .tesla-slide__bckg--enter .tesla-slide__bckg-fill {
bottom: 0;
top: 100%;
transform: translateY(10px) scale(0.9);
}
.tesla-slide__bckg--exit .tesla-slide__bckg-fill {
transition: all 0.6s ease-in 0.1s, background 0s;
height: 0;
top: 100%;
bottom: 0;
opacity: 0.2;
transform: translateY(10px) scale(0.9);
}
.tesla-slide__bckg--exit:before {
transition: all 0.6s ease-in-out 0.2s;
}
.tesla-slide__bckg--exit:before, .tesla-slide__bckg--exit:after {
opacity: 0;
}
.animation-back .tesla-slide__bckg--exit .tesla-slide__bckg-fill {
top: 0;
bottom: 100%;
transform: translateY(-20px) scale(1.1);
}
/* Slide Item Aside
-------------------------------------------------------------- */
.tesla-slide-aside {
text-align: left;
/* Slide Item Whole name
-------------------------------------------------------------- */
/* Slide Item Name
-------------------------------------------------------------- */
/* Slide Item Description
-------------------------------------------------------------- */
/* Slide Button
-------------------------------------------------------------- */
}
@media only screen and (max-width:767px) {
.tesla-slide-aside {
padding-left: 20px;
}
}
@media only screen and (max-width:480px) {
.tesla-slide-aside {
padding-left: 0;
}
}
.tesla-slide-aside__wholename {
height: auto;
}
@media only screen and (min-width:768px) {
.tesla-slide-aside__wholename {
height: 75px;
}
}
.tesla-slide-aside__wholename > span {
height: 55px;
vertical-align: top;
}
@media only screen and (min-width:768px) {
.tesla-slide-aside__wholename > span {
height: 75px;
}
}
.tesla-slide-aside__name {
position: relative;
display: inline-block;
width: 40%;
overflow: hidden;
}
@media only screen and (max-width:767px) {
.tesla-slide-aside__name {
width: 65%;
}
}
@media only screen and (max-width:480px) {
.tesla-slide-aside__name {
width: 230px;
}
}
.tesla-slide-aside__name-part {
position: absolute;
left: 0;
top: 0;
opacity: 1;
display: block;
margin-left: 15px;
transition: top 0.5s ease-out 0.1s, opacity 0.4s linear;
}
.tesla-slide-aside__name-part--enter {
left: 0;
top: 100%;
opacity: 0;
}
.animation-back .tesla-slide-aside__name-part--enter {
top: -100%;
}
.tesla-slide-aside__name-part--exit {
left: 0;
top: -100%;
opacity: 0;
transition: top 0.5s ease-out 0.4s, opacity 0.4s linear 0.4s;
}
.animation-back .tesla-slide-aside__name-part--exit {
top: 100%;
}
.tesla-slide-aside__desc {
position: relative;
margin: 10px 0 0;
max-width: 420px;
height: 5rem;
overflow: hidden;
}
@media only screen and (min-width:768px) {
.tesla-slide-aside__desc {
margin-top: 40px;
}
}
.tesla-slide-aside__desc-text {
position: absolute;
display: block;
left: 0;
top: 0;
bottom: 0;
margin: 0;
line-height: 2.5rem;
letter-spacing: 0.5px;
font-weight: 300;
opacity: 1;
transition: top 0.4s ease-out 0.2s, bottom 0.4s ease-out 0.2s, opacity 0.4s ease-out 0.3s, line-height 0.3s ease-out 0.5s;
}
.tesla-slide-aside__desc-text--enter {
left: 0;
top: 100%;
bottom: 0;
opacity: 0;
line-height: 4rem;
}
.animation-back .tesla-slide-aside__desc-text--enter {
top: -100%;
bottom: auto;
line-height: 3rem;
}
.tesla-slide-aside__desc-text--exit {
transition: bottom 0.5s ease-out 0.3s, top 0.5s ease-out 0.3s, opacity 0.4s ease-out 0.3s, line-height 0.3s ease-out 0.2s;
left: 0;
top: auto;
bottom: 100%;
opacity: 0;
line-height: 4rem;
}
.animation-back .tesla-slide-aside__desc-text--exit {
top: 100%;
bottom: auto;
}
.tesla-slide-aside__button {
position: relative;
height: 50px;
margin-top: 25px;
}
@media only screen and (min-width:768px) {
.tesla-slide-aside__button {
margin-top: 50px;
}
}
.tesla-slide-aside__button button {
z-index: 1;
}
/* Slide Params
-------------------------------------------------------------- */
.tesla-slide-params {
margin: 250px 0 30px;
}
@media only screen and (max-width:480px) {
.tesla-slide-params {
margin-top: 350px;
}
}
@media only screen and (min-width:768px) {
.tesla-slide-params {
margin-top: 130px;
}
}
@media only screen and (min-width:992px) {
.tesla-slide-params {
margin: 170px 0 20px;
}
}
@media only screen and (min-width:1800px) {
.tesla-slide-params {
margin: 225px 0 80px;
}
}
.tesla-slide-params__list {
display: flex;
justify-content: center;
margin: 0 auto;
width: 100%;
}
@media only screen and (min-width:1200px) {
.tesla-slide-params__list {
padding-left: 10%;
}
}
.tesla-slide-params__item {
text-align: center;
width: 190px;
}
.tesla-slide-params__item:first-of-type .tesla-slide-params__wrapper {
padding-left: 10px;
width: 160px;
text-align: left;
}
.tesla-slide-params__item:first-of-type .tesla-slide-params__wrapper .tesla-slide-params__value {
padding-left: 5px;
}
.tesla-slide-params__wrapper {
display: inline-block;
margin-bottom: 10px;
}
.tesla-slide-params__value {
padding: 0 8px;
font-size: 3.1rem;
transition: opacity 0.05s ease-in;
}
@media only screen and (min-width:768px) {
.tesla-slide-params__value {
font-size: 4.8rem;
}
}
.tesla-slide-params__value--enter {
opacity: 0.7;
}
.tesla-slide-params__value--exit {
opacity: 0;
}
.tesla-slide-params__prefix {
display: inline-block;
vertical-align: top;
font-size: 2rem;
}
@media only screen and (min-width:768px) {
.tesla-slide-params__prefix {
font-size: 3rem;
}
}
.tesla-slide-params__name {
margin-top: -5px;
font-size: 1.4rem;
}
.tesla-slide-params__sufix {
font-family: "BebasNeue", "Helvetica", "Arial", sans-serif;
letter-spacing: 0.9px;
font-size: initial;
}
/* Slider
-------------------------------------------------------------- */
.tesla-slider {
padding-top: 20px;
/* Mouse scroll
-------------------------------------------------------------- */
}
@media only screen and (min-width:992px) {
.tesla-slider {
padding-top: 40px;
}
}
@media only screen and (min-width:1200px) {
.tesla-slider {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
padding-top: 0;
}
}
@media only screen and (min-width:1800px) {
.tesla-slider {
padding-top: 135px;
}
}
.tesla-slider__scroll {
order: 3;
width: 100%;
}
.tesla-slider__scroll img {
display: block;
margin: 0 auto;
}
/* Slider Navigation
-------------------------------------------------------------- */
.tesla-slider-navigation {
/* Slider Navigation List
-------------------------------------------------------------- */
/* Slider Navigation List item
-------------------------------------------------------------- */
}
@media only screen and (min-width:1200px) {
.tesla-slider-navigation {
order: 2;
width: 150px;
}
}
.tesla-slider-navigation__list {
display: flex;
margin: 0;
justify-content: space-around;
text-align: center;
}
@media only screen and (min-width:768px) {
.tesla-slider-navigation__list {
margin: 5px;
}
}
@media only screen and (min-width:1200px) {
.tesla-slider-navigation__list {
display: block;
order: 2;
text-align: right;
}
}
.tesla-slider-navigation__item {
display: inline-block;
padding: 0 5px;
text-transform: uppercase;
line-height: 1;
font-size: 1.2rem;
}
@media only screen and (min-width:768px) {
.tesla-slider-navigation__item {
font-size: 1.5rem;
letter-spacing: 0.6px;
}
}
@media only screen and (min-width:1200px) {
.tesla-slider-navigation__item {
display: block;
margin-top: 90px;
}
}
@media only screen and (min-width:1800px) {
.tesla-slider-navigation__item {
margin-top: 95px;
}
}
.tesla-slider-navigation__item:first-of-type {
margin-top: 0;
}
.tesla-slider-navigation__link--active {
font-size: 1.2rem;
transition: font-size 0.3s linear, color 0.2s linear 0.8s;
}
@media only screen and (min-width:768px) {
.tesla-slider-navigation__link--active {
font-size: 1.4rem;
}
}
@media only screen and (min-width:1200px) {
.tesla-slider-navigation__link--active {
font-size: 1.8rem;
}
}
Tesla Roadster Javascript Code
function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}const { TransitionGroup, CSSTransition } = ReactTransitionGroup;
/* Slides data
-------------------------------------------------------------- */
const roadsterFloorImg = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/roadster-floor.png',
roadsterImg = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/roadster-car.png',
truckFloorImg = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/truck-floor.png',
truckImg = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/truck-car.png';
const slides = [
{
id: 1,
name: "Model S",
desc: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et ",
color: "#0047fd",
imgFloorUrl: truckFloorImg,
imgUrl: truckImg,
topSpeed: 75,
mph: 4.5,
mileRange: 400,
bckgHeight: 300,
carShadowHeight: 300,
shadowOpacity: 0.2 },
{
id: 2,
name: "Model X",
desc:
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
color: "#ee0101",
imgFloorUrl: roadsterFloorImg,
imgUrl: roadsterImg,
topSpeed: 255,
mph: 3,
mileRange: 520,
bckgHeight: 250,
carShadowHeight: 0,
shadowOpacity: 0.5 },
{
id: 3,
name: "Model 3",
desc:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et ",
color: "#0047fd",
imgFloorUrl: truckFloorImg,
imgUrl: truckImg,
topSpeed: 55,
mph: 6,
mileRange: 550,
bckgHeight: 300,
carShadowHeight: 250,
shadowOpacity: 0.2 },
{
id: 4,
name: "Roadster",
desc:
"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
color: "#ee0101",
imgFloorUrl: roadsterFloorImg,
imgUrl: roadsterImg,
topSpeed: 250,
mph: 1.9,
mileRange: 620,
bckgHeight: 340,
carShadowHeight: 150,
shadowOpacity: 0.5 },
{
id: 5,
name: "Semi truck",
desc:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore",
color: "#0047fd",
imgFloorUrl: truckFloorImg,
imgUrl: truckImg,
topSpeed: 65,
mph: 5,
mileRange: 500,
bckgHeight: 390,
carShadowHeight: 400,
shadowOpacity: 0.2 }];
/* Set CSS Variables
*/
class SetCSSVariables extends React.Component {
componentWillReceiveProps(props) {
Object.keys(props.cssVariables).forEach(function (key) {
document.documentElement.style.setProperty(key, props.cssVariables[key]);
});
}
render() {
return this.props.children;
}}
/* Slide aside
-------------------------------------------------------------- */_defineProperty(SetCSSVariables, "PropTypes", { cssVariables: PropTypes.object.isRequired, className: PropTypes.string });
function SlideAside(props) {
const activeCar = props.activeCar;
return /*#__PURE__*/(
React.createElement("div", { className: "tesla-slide-aside" }, /*#__PURE__*/
React.createElement("h1", { className: "tesla-slide-aside__wholename" }, /*#__PURE__*/
React.createElement("span", null, "Tesla"), /*#__PURE__*/
React.createElement(TransitionGroup, { component: "span", className: "tesla-slide-aside__name" }, /*#__PURE__*/
React.createElement(CSSTransition, {
key: activeCar.name,
timeout: { enter: 800, exit: 1000 },
className: "tesla-slide-aside__name-part",
classNames: "tesla-slide-aside__name-part-",
mountOnEnter: true,
unmountOnExit: true }, /*#__PURE__*/
React.createElement("span", null, activeCar.name)))), /*#__PURE__*/
React.createElement(TransitionGroup, { className: "tesla-slide-aside__desc" }, /*#__PURE__*/
React.createElement(CSSTransition, {
key: activeCar.desc,
timeout: { enter: 900, exit: 1200 },
className: "tesla-slide-aside__desc-text",
classNames: "tesla-slide-aside__desc-text-",
mountOnEnter: true,
unmountOnExit: true }, /*#__PURE__*/
React.createElement("p", null, activeCar.desc))), /*#__PURE__*/
React.createElement("div", { className: "tesla-slide-aside__button" }, /*#__PURE__*/
React.createElement("button", { className: "button" }, "Reserve now"), /*#__PURE__*/
React.createElement(TransitionGroup, null, /*#__PURE__*/
React.createElement(CSSTransition, {
key: activeCar.color,
timeout: { enter: 800, exit: 1000 },
mountOnEnter: true,
unmountOnExit: true,
classNames: "button__border-" }, /*#__PURE__*/
React.createElement(SetCSSVariables, { cssVariables: { '--btn-color': activeCar.color } }, /*#__PURE__*/
React.createElement("span", { className: "button__border" })))))));
}
SlideAside.PropTypes = {
activeCar: PropTypes.object.isRequired };
/* Slide animate values
-------------------------------------------------------------- */
function animate(render, duration, easing, next = () => null) {
const start = Date.now();
(function loop() {
const current = Date.now(),
delta = current - start,
step = delta / duration;
if (step > 1) {
render(1);
next();
} else {
requestAnimationFrame(loop);
render(easing(step * 2));
}
})();
}
const myEasing = BezierEasing(.4, -0.7, .1, 1.5);
class AnimValue extends React.Component {constructor(...args) {super(...args);_defineProperty(this, "node",
null);_defineProperty(this, "timeout",
null);_defineProperty(this, "setValue",
(value, step) => {
if (!this.node) {
return;
}
if (step === 1) {
this.node.style.opacity = 1;
} else {
this.node.style.opacity = 0.7;
}
this.node.innerHTML = value;
});}animate(previousValue, newValue, applyFn) {window.clearTimeout(this.timeout);const diff = newValue - previousValue;const renderFunction = (step) => {this.timeout = setTimeout(() => {applyFn(this.props.transformFn(previousValue + diff * step, step), step);}, this.props.delay);};animate(renderFunction, this.props.duration, myEasing);}
componentDidMount() {
this.animate(0, this.props.value, this.setValue);
}
componentWillReceiveProps(props) {
let previousValue = this.props.value;
if (previousValue !== props.value) {
this.animate(previousValue, props.value, this.setValue);
}
}
componentWillUnmount() {
window.clearTimeout(this.timeout);
this.timeout = null;
}
render() {
return /*#__PURE__*/React.createElement("span", { className: this.props.className, children: "0", ref: node => this.node = node });
}}_defineProperty(AnimValue, "defaultProps", { delay: 0, duration: 800, transformFn: value => Math.floor(value) });
class AnimateValue extends React.Component {
render() {
return /*#__PURE__*/(
React.createElement(AnimValue, {
className: this.props.className,
delay: this.props.delay,
value: this.props.value,
transformFn: (value, step) =>
step === 1 ? value % 1 != 0 ? value.toFixed(1) : value : Math.abs(Math.floor(value)) }));
}}
let DELAY_TOP_SPEED = 200,
DELAY_MPH = 700,
DELAY_MILE_RANG = 1200;
class SlideParams extends React.Component {
componentWillReceiveProps(props) {
if (!props.animationForward) {
DELAY_TOP_SPEED = 1200;
DELAY_MILE_RANG = 200;
} else {
DELAY_TOP_SPEED = 200;
DELAY_MILE_RANG = 1200;
}
}
render() {
const { activeCar } = this.props;
return /*#__PURE__*/(
React.createElement("div", { className: "tesla-slide-params" }, /*#__PURE__*/
React.createElement("ul", { className: "tesla-slide-params__list" }, /*#__PURE__*/
React.createElement("li", { className: "tesla-slide-params__item" }, /*#__PURE__*/
React.createElement("div", { className: "tesla-slide-params__wrapper" }, /*#__PURE__*/
React.createElement("span", { className: "tesla-slide-params__prefix" }, "+"), /*#__PURE__*/
React.createElement(AnimateValue, {
className: "tesla-slide-params__value",
value: activeCar.topSpeed,
delay: DELAY_TOP_SPEED }), /*#__PURE__*/
React.createElement("span", { className: "tesla-slide-params__sufix" }, "mph")), /*#__PURE__*/
React.createElement("p", { className: "tesla-slide-params__name" }, "Top speed")), /*#__PURE__*/
React.createElement("li", { className: "tesla-slide-params__item" }, /*#__PURE__*/
React.createElement("div", { className: "tesla-slide-params__wrapper" }, /*#__PURE__*/
React.createElement(AnimateValue, {
className: "tesla-slide-params__value",
value: activeCar.mph,
delay: DELAY_MPH }), /*#__PURE__*/
React.createElement("span", { className: "tesla-slide-params__sufix" }, "s")), /*#__PURE__*/
React.createElement("p", { className: "tesla-slide-params__name" }, "0-60 mph")), /*#__PURE__*/
React.createElement("li", { className: "tesla-slide-params__item" }, /*#__PURE__*/
React.createElement("div", { className: "tesla-slide-params__wrapper" }, /*#__PURE__*/
React.createElement(AnimateValue, {
className: "tesla-slide-params__value",
value: activeCar.mileRange,
delay: DELAY_MILE_RANG }), /*#__PURE__*/
React.createElement("span", { className: "tesla-slide-params__sufix" }, "mi")), /*#__PURE__*/
React.createElement("p", { className: "tesla-slide-params__name" }, "Mile Range")))));
}}_defineProperty(SlideParams, "PropTypes", { activeCar: PropTypes.object.isRequired, animationForward: PropTypes.bool.isRequired });
class Slide extends React.Component {constructor(...args) {super(...args);_defineProperty(this, "handleEnter",
e => {
this.props.setAnimationState(this.props.ANIMATION_PHASES.STOP);
});}
render() {
const { activeSlide, animationForward } = this.props;
return /*#__PURE__*/(
React.createElement("div", { className: `tesla-slide ${animationForward ? 'animation-forward' : 'animation-back'}` }, /*#__PURE__*/
React.createElement(SlideAside, { activeCar: activeSlide }), /*#__PURE__*/
React.createElement(TransitionGroup, null, /*#__PURE__*/
React.createElement(CSSTransition, {
key: activeSlide.name,
timeout: { enter: 800, exit: 1000 },
classNames: "tesla-slide__bckg-",
mountOnEnter: true,
unmountOnExit: true }, /*#__PURE__*/
React.createElement(SetCSSVariables, {
cssVariables: {
'--car-color': activeSlide.color,
'--bckg-height': activeSlide.bckgHeight + 'px',
'--shadow-opacity': activeSlide.shadowOpacity,
'--car-shadow-height': activeSlide.carShadowHeight + 'px' } }, /*#__PURE__*/
React.createElement("div", { className: "tesla-slide__bckg" }, /*#__PURE__*/
React.createElement("div", { className: "tesla-slide__bckg-fill" }))))), /*#__PURE__*/
React.createElement(TransitionGroup, null, /*#__PURE__*/
React.createElement(CSSTransition, {
key: activeSlide.name,
timeout: { enter: 700, exit: 1200 },
classNames: "tesla-slide__img-",
mountOnEnter: true,
unmountOnExit: true,
onEntered: this.handleEnter }, /*#__PURE__*/
React.createElement("div", { className: "tesla-slide__img" }, /*#__PURE__*/
React.createElement("img", { className: "tesla-slide__img-floor", src: activeSlide.imgFloorUrl, alt: "" }), /*#__PURE__*/
React.createElement("img", { className: "tesla-slide__img-car", src: activeSlide.imgUrl, alt: "" })))), /*#__PURE__*/
React.createElement(SlideParams, { activeCar: activeSlide, animationForward: animationForward })));
}}_defineProperty(Slide, "PropTypes", { activeSlide: PropTypes.object.isRequired, animationForward: PropTypes.bool.isRequired, setAnimationState: PropTypes.func.isRequired, ANIMATION_PHASES: PropTypes.object.isRequired });
class SliderNavigation extends React.Component {
render() {
return /*#__PURE__*/(
React.createElement("div", { className: "tesla-slider-navigation" }, /*#__PURE__*/
React.createElement("ul", { className: "tesla-slider-navigation__list" },
this.props.carsNames.map((car) => /*#__PURE__*/
React.createElement("li", { key: car.id, className: "tesla-slider-navigation__item" }, /*#__PURE__*/
React.createElement("a", {
href: "#",
onClick: event => {
event.preventDefault();
this.props.setActiveSlide(this.props.carsNames.indexOf(car));
},
className: `tesla-slider-navigation__link ${
this.props.carsNames[this.props.activeSlide] === car ?
'tesla-slider-navigation__link--active' :
''
}`,
style: {
color: this.props.carsNames[this.props.activeSlide] === car ? car.color : '' } },
car.name))))));
}}_defineProperty(SliderNavigation, "PropTypes", { setActiveSlide: PropTypes.func.isRequired, carsNames: PropTypes.array.isRequired });
const logoTesla = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/logoTesla.svg',
mouseImg = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/mouse.svg',
hamburger = 'https://s3-us-west-2.amazonaws.com/s.cdpn.io/1780138/hamburger.svg';
/* Slider
-------------------------------------------------------------- */
const ANIMATION_PHASES = {
PENDING: 'PENDING',
STOP: 'STOP' };
class Slider extends React.Component {constructor(...args) {super(...args);_defineProperty(this, "state",
{
activeSlide: 0,
animationForward: true,
slidesCount: slides.length,
animationState: null });_defineProperty(this, "slider",
{
header: '',
content: '' });_defineProperty(this, "setAnimationState",
animationState => this.setState({ animationState }));_defineProperty(this, "setActiveSlide",
slideId => {
this.setState({
activeSlide: slideId,
animationForward: this.state.activeSlide < slideId ? true : false });
this.setAnimationState(ANIMATION_PHASES.PENDING);
});_defineProperty(this, "timeout",
null);_defineProperty(this, "handleScroll",
e => {
let sliderHeight = this.slider.content.clientHeight,
headerHeight = this.slider.header.clientHeight;
if (window.innerHeight < sliderHeight + headerHeight) {
return; // do not handle scroll effect when window height is smaller than slider plus header height
}
e.preventDefault();
window.clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
if (e.deltaY < 0 && this.state.activeSlide !== 0) {
this.setActiveSlide(this.state.activeSlide - 1);
}
if (e.deltaY > 0 && this.state.activeSlide !== this.state.slidesCount - 1) {
this.setActiveSlide(this.state.activeSlide + 1);
}
}, 50);
});}componentDidMount() {this.setState({ activeSlide: 3 });this.setAnimationState(ANIMATION_PHASES.PENDING);this.slider.header = document.querySelector('.tesla-header');this.slider.content = document.querySelector('.tesla-slider');document.body.addEventListener('wheel', this.handleScroll);}
componentWillUnmount() {
document.body.removeEventListener('wheel', this.handleScroll);
window.clearTimeout(this.timeout);
this.timeout = null;
}
render() {
return /*#__PURE__*/(
React.createElement("div", { className: "tesla-slider" }, /*#__PURE__*/
React.createElement(SliderNavigation, {
activeSlide: this.state.activeSlide,
setActiveSlide: this.setActiveSlide,
carsNames: slides.map(slide => ({
id: slide.id,
name: slide.name,
color: slide.color })) }), /*#__PURE__*/
React.createElement(Slide, {
animationForward: this.state.animationForward,
activeSlide: slides[this.state.activeSlide],
animationState: this.state.animationState,
setAnimationState: this.setAnimationState,
ANIMATION_PHASES: ANIMATION_PHASES }), /*#__PURE__*/
React.createElement("div", { className: "tesla-slider__scroll" }, /*#__PURE__*/
React.createElement("img", { src: mouseImg, alt: "" }))));
}}
/* Header
-------------------------------------------------------------- */
function Header() {
return /*#__PURE__*/(
React.createElement("div", { className: "tesla-header" }, /*#__PURE__*/
React.createElement("div", { className: "tesla-header__logo" }, /*#__PURE__*/
React.createElement("img", { src: logoTesla, alt: "" })), /*#__PURE__*/
React.createElement("div", { className: "tesla-header__nav" }, /*#__PURE__*/
React.createElement("img", { src: hamburger, alt: "" }))));
}
/* App
-------------------------------------------------------------- */
class App extends React.Component {
render() {
return /*#__PURE__*/(
React.createElement("div", { className: "container" }, /*#__PURE__*/
React.createElement(Header, null), /*#__PURE__*/
React.createElement(Slider, null)));
}}
ReactDOM.render( /*#__PURE__*/React.createElement(App, null), document.getElementById("root"));
Live Preview:
See the Pen Untitled by Developergtm (@developergtm) on CodePen.