<header class="header">
<nav class="navbar">
<span>darthvaders</span>
<span>menu</span>
</nav>
<h1 class="header__title">loading 0%</h1>
<div class="headerActions">
<ul class="headerActions__list">
<li>ki.</li>
<li>ara.</li>
<li>sh.</li>
</ul>
<a target="_blank" href="https://twitter.com/kiarash_zar" class="headerActions__action">join the club</a>
<span class="headerActions__control">sound off</span>
</div>
</header>
*, *::after, *::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
html, body {
height: 100%;
touch-action: none;
}
body {
position: relative;
font-family: 'Montserrat', sans-serif;
background-image: radial-gradient(rgba(0, 0, 0, 0.8) 0%, #000 35%);
color: rgb(241, 241, 241);
text-transform: uppercase;
user-select: none;
}
.header {
width: 100%;
height: 100%;
position: absolute;
padding: 5rem 4rem;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.header__title {
font-size: 8vw;
align-self: center;
width: 100%;
text-align: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -1;
}
.navbar {
display: flex;
justify-content: space-between;
font-size: 1.5rem;
flex: 1;
}
.headerActions {
display: flex;
align-items: flex-end;
flex: 1;
}
.headerActions__list {
list-style-type: none;
display: flex;
flex: 1;
font-size: 1.2rem;
}
.headerActions__list > li:not(:last-child) {
margin-right: 1rem;
}
.headerActions__action {
background: #fff;
outline: none;
border: none;
color: #000;
font-size: 1.5rem;
padding: 2rem 2.5rem;
text-transform: uppercase;
font-family: inherit;
transition: 0.2s;
position: relative;
cursor: pointer;
tap-highlight-color: transparent;
text-decoration: none;
}
.headerActions__action:hover {
box-shadow: 0 1rem 3rem rgba(255, 255, 255, 0.3);
}
.headerActions__control {
display: flex;
flex: 1;
justify-content: flex-end;
font-size: 1.2rem;
}
@media (max-width: 1200px) {
html {
font-size: 58%;
}
}
@media (max-width: 768px) {
html {
font-size: 55%;
}
}
@media (max-width: 768px) and (orientation: portrait) {
.header__title {
font-size: 11vw;
}
}
@media (max-width: 356px) {
html {
font-size: 50%;
}
}
@media (min-aspect-ratio: 3/1) {
html {
font-size: 35%;
}
}
const headerTitle = document.querySelector('.header__title');
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.z = 8;
const mainLight = new THREE.AmbientLight (0x404040, 10);
scene.add(mainLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 100);
directionalLight.position.set(0, 5, 0);
directionalLight.castShadow = true;
scene.add(directionalLight);
const pointLight = new THREE.PointLight(0xc4c4c4, 20);
pointLight.position.set(0, 250, 500);
scene.add(pointLight);
const loadingManager = new THREE.LoadingManager();
loadingManager.onProgress = (_, loaded, total) => {
const loadingPercentage = Math.floor(loaded / total) * 100;
headerTitle.textContent = loadingPercentage === 100 ? 'darthvaders' : `loading ${loadingPercentage}%`;
};
const loader = new THREE.GLTFLoader(loadingManager);
const dracoLoader = new THREE.DRACOLoader();
dracoLoader.setDecoderPath('https://darthvader.surge.sh/draco/');
loader.setDRACOLoader(dracoLoader);
const position = new THREE.Vector3();
const initializeAnimation = model => {
let isInitiallyAnimating = true;
const render = () => {
renderer.render(scene, camera);
};
render();
gsap.to(model.rotation, 1, {
z: 0,
onComplete: () => {
isInitiallyAnimating = false;
},
onUpdate: render,
}).delay(0.2);
const limitTo = (value, { maximum, minimum }) => {
if (value > maximum) return maximum;
else if (value < minimum) return minimum;
return value;
};
const handlePointerMove = ({ clientX, clientY }) => {
if (isInitiallyAnimating) return;
const centerPoint = {
x: window.innerWidth / 2,
y: window.innerHeight / 2,
};
const z = (clientX - centerPoint.x) / 1000;
const x = -1 * Math.PI / 2 + (clientY - centerPoint.y) / 1000;
gsap.to(model.rotation, 0.4, {
x,
z: limitTo(z, { maximum: Math.PI / 2.2, minimum: -Math.PI / 2.2 }),
onUpdate: render,
});
};
window.addEventListener('pointermove', handlePointerMove);
};
const handleLoad = gltf => {
const model = gltf.scene.children[0];
model.rotation.z = Math.PI;
scene.add(model);
initializeAnimation(model);
};
const handleWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.render(scene, camera);
};
loader.load('https://darthvader.surge.sh/model.gltf', handleLoad);
window.addEventListener('resize', handleWindowResize);
This Pen doesn't use any external CSS resources.