Feature Coming Soon!
The newsletter functionality is under development.
This project showcases a stunning 3D Car Animation Model, built using HTML, CSS, and JavaScript, leveraging the `
Key features include a loading screen, a continuously scrolling background title, and a vertical Swiper.js carousel that controls different views and interactive elements of the car model. Users can navigate through slides to learn more about the car, personalize its paint, and interact with the 3D model's camera. The project is designed to be fully responsive, ensuring a seamless experience across various devices and screen sizes.
The HTML structure of the 3D Car Animation Model is built around a main `div` with the ID `page`, which serves as the primary container. It includes a loading screen, a `<model-viewer>` component to display the 3D car model, and a dynamic background title. A Swiper.js container (`div` with class `swiper`) houses multiple `section` elements, each representing a distinct slide. These slides contain interactive content such as car details, personalization options (like color selection buttons), and navigation links. A `picture` element is used for the responsive background image, ensuring optimal image loading across different screen resolutions. This modular structure allows for easy management of content and interactive elements within the 3D environment.
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title> 3D Car Animation Model | Coders_Section </title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@300;500;800&display=swap" rel="stylesheet">
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script><link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<div id="page" class="h-full bg-gradient-to-r from-transparent to-slate-200/30 bg-slate-200 text-slate-900 transition-colors duration-[2000ms] antialiased relative overflow-hidden select-none">
<div id="loading" class="absolute inset-0 z-50 bg-slate-200/80 flex items-center justify-center">
<svg class="animate-spin h-10 w-10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="2">
<circle class="opacity-20" cx="12" cy="12" r="11" />
<path d="m23 12c0 6.1-4.9 11-11 11" />
</g>
</svg>
</div>
<model-viewer class="absolute left-0 top-0 w-full h-full z-30 pointer-events-none"
src="https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/scene.gltf?v=1674149863924"
exposure="1"
shadow-intensity="3"
camera-orbit="0deg 10deg 20%"
camera-target="-9.5m -8m 5m"></model-viewer>
<div class="absolute left-0 top-1/2 -translate-y-1/2 z-0 pointer-events-none">
<div class="title opacity-0 text-[clamp(200px,40vh,500px)] font-bold text-slate-900/5 opacity-0 pointer-events-none flex whitespace-nowrap will-change-transform">
<span class="mx-20">240K GT</span>
<span class="mx-20">240K GT</span>
<span class="mx-20">240K GT</span>
<span class="mx-20">240K GT</span>
<span class="mx-20">240K GT</span>
<span class="mx-20">240K GT</span>
</div>
</div&
<div class="swiper w-full h-full absolute left-0 top-0 z-40 opacity-0">
<div class="swiper-wrapper">
<section class="swiper-slide w-full h-full flex flex-col justify-end relative p-[5vw]">
<div id="inner-1" class="flex flex-col items-start gap-4 lg:gap-8 w-full sm:w-2/3 lg:w-1/3 3xl:w-1/4 md:text-lg">
<h1 class="text-[clamp(26px,4vw,60px)] leading-none font-light uppercase">
Datsun
<br class="hidden lg:block" />
<span class="font-bold">240K GT</span>
</h1>
<p>
Introducing a Masterpiece, the combination of all Datsun's great automotive innovations.
</p>
<strong class="hidden lg:block">
From 30,500 €
</strong>
<div class="flex flex-wrap gap-2">
<a href="#section-2" data-slide-to="1" class="uppercase px-6 py-3 md:px-12 md:py-4 rounded-full text-xs md:text-base tracking-wider text-slate-50 bg-blue-700 hover:bg-blue-600 active:bg-blue-900 transition-colors grow text-center">
Learn more
</a>
<a href="#" target="_blank" rel="noopener" class="uppercase px-6 py-3 md:px-12 md:py-4 rounded-full text-xs md:text-base tracking-wider bg-transparent hover:bg-slate-50/50 active:bg-white transition-colors grow text-center">Contact us</a>
</div>
</div>
</section>
<section class="swiper-slide w-full h-full flex flex-col items-end justify-end lg:justify-center relative z-50 px-[5vw] py-[5vh]">
<div id="inner-2" class="flex flex-col items-start gap-5 lg:gap-8 w-full sm:w-2/3 lg:w-1/3 2xl:w-1/4 p-[2.5vw] mb-8 lg:mb-0 sm:box-content rounded-xl sm:rounded-[2vw] md:text-lg text-slate-50 bg-zinc-900/20 backdrop-blur-lg">
<h2 class="text-[clamp(22px,3vw,36px)] leading-[110%]">
A compact car with an exceptional power-to-weight ratio
</h2>
<p class="mb-10 lg:mb-7">
In addition to all the usual Datsun free extra, the 240K gives you ultimate refinements like electric rear window defroster; adjustable tilt steering wheel.
</p>
<a href="#section-3" data-slide-to="2" class="uppercase px-12 py-4 rounded-full text-xs md:text-base tracking-wider text-slate-50 bg-blue-700 hover:bg-blue-600 active:bg-blue-900 transition-colors absolute bottom-0 translate-y-1/2">
Personalise
</a>
</div>
</section>
<section class="swiper-slide w-full h-full flex flex-col items-center relative px-[5vw] py-[5vh]">
<div id="inner-3" class="relative z-50 flex flex-col items-center gap-4 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.9)]">
<h4 class="text-[clamp(22px,3vw,36px)]">
Paint
</h4>
<div class="flex gap-8">
<button aria-label="White" data-color="#CBD5E1" class="active relative rounded-full w-[40px] h-[30px] bg-gradient-to-r from-slate-50 to-slate-500 bg-slate-200 outline-0 hover:scale-110 focus:scale-110 transition-all"></button>
<button aria-label="Blue" data-color="#355F99" class="relative rounded-full w-[40px] h-[30px] bg-gradient-to-r from-blue-500 to-blue-900 bg-blue-700 outline-0 hover:scale-110 focus:scale-110 transition-all"></button>
<button aria-label="Red" data-color="#923939" class="relative rounded-full w-[40px] h-[30px] bg-gradient-to-r from-red-400 to-red-800 bg-red-600 outline-0 hover:scale-110 focus:scale-110 transition-all"></button>
</div>
</div>
</section>
</div>
<div class="swiper-pagination"></div>
</div>
<picture class="absolute left-0 top-1/2 w-full h-full z-0 opacity-0">
<source srcSet="https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-3000.jpg?v=1674210862901"
media="(min-width: 2000px)" />
<source srcSet="https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-2000.jpg?v=1674210859490, https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-3000.jpg?v=1674210862901 2x"
media="(min-width: 1000px)" />
<source srcSet="https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-1000.jpg?v=1674210857284, https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-2000.jpg?v=1674210859490 2x"
media="(min-width: 500px)" />
<img class="w-full h-full object-cover"
srcSet="https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-1000.jpg?v=1674210857284 2x"
src="https://cdn.glitch.global/ccaf12bb-59b0-46bb-bd74-b9467ca22e3d/bg-road-500.jpg?v=1674211189312"
alt="Landscape" />
</picture>
</div>
<!-- partial -->
<script src='https://cdnjs.cloudflare.com/ajax/libs/Swiper/8.4.6/swiper-bundle.min.js'></script>
<script src='https://unpkg.co/gsap@3/dist/gsap.min.js'></script>
<script src='https://unpkg.com/gsap@3/dist/ScrollTrigger.min.js'></script><script src="./script.js"></script>
</body>
</html>
The CSS for the 3D Car Animation Model is designed to create a visually immersive and responsive experience. It sets the base styles for the HTML and body, ensuring full-page coverage and a consistent font. The `
html,
body {
width: 100%;
height: 100%;
}
body {
font-family: 'Manrope', sans-serif;
}
model-viewer {
--poster-color: #e2e8f0;
--progress-bar-color: rgba(30, 41, 59, .5);
--progress-bar-height: 10px;
}
[data-color]::before {
content: "";
display: block;
position: absolute;
inset: -5px;
border: 2px solid transparent;
border-radius: 999px;
}
[data-color].active::before,
[data-color]:focus::before {
border-color: white;
}
The JavaScript for the 3D Car Animation Model orchestrates the entire interactive experience. It initializes Swiper.js for vertical slide navigation and uses GSAP (GreenSock Animation Platform) for smooth animations. Key functionalities include: fading out the loading screen once the 3D model is loaded, setting up an infinite horizontal scroll animation for the background title, and dynamically adjusting the 3D car's camera position and exposure based on the active Swiper slide. It also handles changing the car's paint color by interacting with the `
/* VARIABLES */
const page = document.getElementById('page'),
loading = document.getElementById('loading'),
slider = document.querySelector('.swiper'),
inner1 = document.getElementById('inner-1'),
inner2 = document.getElementById('inner-2'),
inner3 = document.getElementById('inner-3'),
car = document.querySelector('model-viewer'),
slideToButtons = document.querySelectorAll('[data-slide-to]'),
colorButtons = document.querySelectorAll('[data-color]'),
title = document.querySelectorAll('.title'),
bgImage = document.querySelector('picture');
const innerAnimationActive = {
duration: 1,
delay: 0.5,
ease: Power4.easeOut,
autoAlpha: 1,
yPercent: 0,
};
const innerAnimationHidden = {
duration: 1,
ease: Power4.easeOut,
autoAlpha: 0,
yPercent: -20,
};
/* VERTICAL SLIDER */
const swiper = new Swiper(slider, {
direction: 'vertical',
speed: 1500,
grabCursor: true,
touchRatio: 2,
threshold: 1,
preventInteractionOnTransition: true,
mousewheel: {
forceToAxis: true,
},
keyboard: {
enabled: true,
},
on: {
init: () => {
/* SLIDER & TITLE FADE IN */
gsap.to(slider, {
duration: 1,
ease: Power4.easeOut,
autoAlpha: 1,
});
gsap.to(title, innerAnimationActive);
/* TITLE INFINITE LOOP */
title.forEach(function (e, i) {
let row_width = e.getBoundingClientRect().width;
let row_item_width = e.children[0].getBoundingClientRect().width;
let offset = ((2 * row_item_width) / row_width) * 100 * -1;
let duration = 30 * (i + 1);
gsap.set(e, {
xPercent: 0
});
gsap.to(e, {
duration: duration,
ease: "none",
xPercent: offset,
repeat: -1
});
});
}
},
});
/* ON LOAD */
car.addEventListener('load', (event) => {
/* FADE OUT LOADING SCREEN */
gsap.to(loading, {
duration: 1,
ease: Power4.easeOut,
autoAlpha: 0,
});
/* 3D CHARACTERISTICS */
const materials = car.model.materials,
paint = materials[10];
/* CHANGE CAR PAINT */
paint.pbrMetallicRoughness.setBaseColorFactor('#CBD5E1');
/* CAR POSITION */
const exposure1 = '1',
orbit1 = '0deg 50deg 50%',
exposure2 = '0.4',
orbit2 = '-60deg 60deg 50%',
exposure3 = '1',
orbit3 = '44deg 83deg 50%';
let target1,
target2,
target3;
const setCarPosition = () => {
if (window.innerWidth <= 900) {
target1 = '-9.5m -11.9m 4.2m';
target2 = '-8.8m -12.7m 4.8m';
target3 = '-9.8m -10m 3.8m';
} else {
target1 = '-9.5m -12.9m 2.2m';
target2 = '-5.8m -12.5m 3.8m';
target3 = '-12m -10.7m 1.7m';
}
}
setCarPosition();
const carPosition = (exposure, orbit, target) => {
return (
{
duration: 1.5,
ease: Power4.easeOut,
attr: {
['exposure']: exposure,
['camera-orbit']: orbit,
['camera-target']: target,
}
}
);
};
/* ANIMATION ON LOAD */
gsap.to(car, carPosition(exposure1, orbit1, target1));
/* SLIDE CHANGE */
swiper.on('slideChange', function () {
if ( swiper.activeIndex === 0 ) {
gsap.to(car, carPosition(exposure1, orbit1, target1));
page.classList.remove('bg-zinc-900');
page.classList.add('bg-slate-200');
} else if ( swiper.activeIndex === 1 ) {
gsap.to(car, carPosition(exposure2, orbit2, target2));
page.classList.remove('bg-slate-200');
page.classList.add('bg-zinc-900');
} else if ( swiper.activeIndex === 2 ) {
gsap.to(car, carPosition(exposure3, orbit3, target3));
page.classList.remove('bg-zinc-900');
page.classList.add('bg-slate-200');
}
if ( swiper.activeIndex === 0 ) {
gsap.to(inner1, innerAnimationActive);
gsap.to(title, innerAnimationActive);
} else {
gsap.to(inner1, innerAnimationHidden);
gsap.to(title, innerAnimationHidden);
}
if ( swiper.activeIndex === 1 ) {
gsap.to(inner2, innerAnimationActive);
} else {
gsap.to(inner2, innerAnimationHidden);
}
if ( swiper.activeIndex === 2 ) {
gsap.to(inner3, innerAnimationActive);
gsap.to(bgImage, {
duration: 1,
delay: 1,
ease: Power4.easeOut,
autoAlpha: 1,
yPercent: -50,
});
} else {
gsap.to(inner3, innerAnimationHidden);
gsap.to(bgImage, {
duration: 0.5,
ease: Power4.easeOut,
autoAlpha: 0,
yPercent: 0,
});
}
});
/* WINDOW RESIZE CAR POSITION */
swiper.on('resize', function () {
setCarPosition();
if ( swiper.activeIndex === 0 ) {
gsap.to(car, carPosition(exposure1, orbit1, target1));
} else if ( swiper.activeIndex === 1 ) {
gsap.to(car, carPosition(exposure2, orbit2, target2));
} else if ( swiper.activeIndex === 2 ) {
gsap.to(car, carPosition(exposure3, orbit3, target3));
}
});
/* SLIDE TO */
slideToButtons.forEach((button) => {
button.addEventListener('click', (e) => {
const index = e.target.dataset.slideTo;
if (index !== undefined) {
swiper.slideTo(index);
}
e.preventDefault();
});
});
/* PAINT */
colorButtons.forEach((button) => {
button.addEventListener('click', (e) => {
/* CHANGE COLOR */
const color = e.target.dataset.color;
if (color !== undefined) {
paint.pbrMetallicRoughness.setBaseColorFactor(color);
}
/* BUTTON ACTIVE */
colorButtons.forEach((otherButton) => {
otherButton.classList.remove('active');
});
e.target.classList.add('active');
e.preventDefault();
});
});
});
Watch a live demonstration of the 3D Car Animation Model below.
This 3D Car Animation Model project provides a sophisticated and engaging way to showcase products in an interactive 3D environment. By combining the `<model-viewer>` component with Swiper.js and GSAP, it delivers a smooth, responsive, and visually rich user experience. The ability to dynamically change car colors and camera views adds a layer of personalization and interactivity, making it ideal for automotive configurators, product showcases, or interactive presentations.
You can easily customize this component by:
For optimal performance with 3D models, ensure your `.gltf` or `.glb` files are optimized for web use (e.g., compressed textures, reduced polygon count). Consider implementing a more advanced loading indicator for larger models, and explore using `Intersection Observer` for lazy loading the `<model-viewer>` component if it's not immediately visible on page load.
Click the button below to download the full source code. Download will be ready in 10 seconds.
Receive coding tips and resources updates. No spam.
We respect your privacy. Unsubscribe at any time.