ye / index.html
aminArtistry's picture
Add 2 files
204f71a verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Driving Portfolio | Graphic Designer</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/GLTFLoader.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css">
<style>
body {
margin: 0;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#canvas-container {
position: absolute;
width: 100%;
height: 100%;
z-index: 1;
}
#ui-overlay {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
pointer-events: none;
}
.dashboard {
background: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(10px);
border-radius: 15px;
padding: 1rem;
pointer-events: all;
}
.speedometer {
width: 120px;
height: 120px;
border: 3px solid rgba(255, 255, 255, 0.2);
border-radius: 50%;
position: relative;
}
.speed-needle {
position: absolute;
width: 3px;
height: 50px;
background: #f43f5e;
top: 10px;
left: 50%;
transform-origin: bottom center;
transform: translateX(-50%) rotate(0deg);
transition: transform 0.3s ease-out;
}
.menu-item {
transition: all 0.3s ease;
}
.menu-item:hover {
transform: translateY(-5px);
text-shadow: 0 0 10px rgba(255, 255, 255, 0.7);
}
.world-border {
position: absolute;
border: 2px dashed rgba(255, 255, 255, 0.3);
pointer-events: none;
}
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-10px); }
}
.floating {
animation: float 3s ease-in-out infinite;
}
</style>
</head>
<body class="bg-gray-900 text-white">
<div id="canvas-container"></div>
<div id="ui-overlay" class="flex flex-col justify-between p-6">
<!-- Top Navigation -->
<div class="flex justify-between items-start">
<div class="dashboard flex items-center space-x-4">
<div class="text-center">
<div class="speedometer mx-auto mb-2">
<div class="speed-needle" id="speed-needle"></div>
</div>
<p class="text-sm">SPEED <span id="speed-display">0</span> km/h</p>
</div>
<div class="text-center">
<div class="text-2xl font-bold" id="distance">0</div>
<p class="text-sm">DISTANCE</p>
</div>
</div>
<div class="dashboard p-4">
<h1 class="text-2xl font-bold mb-2">DRIVING PORTFOLIO</h1>
<p class="text-sm opacity-80">Graphic Designer & 3D Artist</p>
</div>
</div>
<!-- Center Content -->
<div class="flex flex-col items-center justify-center h-full -mt-20">
<div class="text-center max-w-2xl mx-auto bg-black bg-opacity-50 p-8 rounded-xl backdrop-filter backdrop-blur-sm">
<h1 class="text-5xl font-bold mb-4 floating">EXPLORE MY WORLD</h1>
<p class="text-lg mb-6">Navigate through this limited 3D environment to discover my graphic design portfolio. Each landmark represents a different aspect of my work.</p>
<button id="start-btn" class="bg-rose-500 hover:bg-rose-600 text-white font-bold py-3 px-8 rounded-full transition-all transform hover:scale-105 pointer-events-auto">
START DRIVING
</button>
</div>
</div>
<!-- Bottom Navigation -->
<div class="flex justify-between items-end">
<div class="dashboard p-4">
<div class="flex space-x-6">
<div class="menu-item pointer-events-auto cursor-pointer">
<i class="fas fa-home text-xl block text-center mb-1"></i>
<span class="text-xs">HOME</span>
</div>
<div class="menu-item pointer-events-auto cursor-pointer">
<i class="fas fa-briefcase text-xl block text-center mb-1"></i>
<span class="text-xs">WORK</span>
</div>
<div class="menu-item pointer-events-auto cursor-pointer">
<i class="fas fa-user text-xl block text-center mb-1"></i>
<span class="text-xs">ABOUT</span>
</div>
<div class="menu-item pointer-events-auto cursor-pointer">
<i class="fas fa-envelope text-xl block text-center mb-1"></i>
<span class="text-xs">CONTACT</span>
</div>
</div>
</div>
<div class="dashboard p-4">
<div class="flex space-x-4">
<a href="#" class="text-xl hover:text-rose-400 transition-colors pointer-events-auto">
<i class="fab fa-behance"></i>
</a>
<a href="#" class="text-xl hover:text-rose-400 transition-colors pointer-events-auto">
<i class="fab fa-dribbble"></i>
</a>
<a href="#" class="text-xl hover:text-rose-400 transition-colors pointer-events-auto">
<i class="fab fa-instagram"></i>
</a>
<a href="#" class="text-xl hover:text-rose-400 transition-colors pointer-events-auto">
<i class="fab fa-linkedin"></i>
</a>
</div>
</div>
</div>
<!-- World Border Indicator -->
<div class="world-border" id="world-border"></div>
</div>
<script>
// Three.js variables
let scene, camera, renderer, car, worldBorder, controls;
let isDriving = false;
let speed = 0;
let maxSpeed = 120;
let distance = 0;
const worldSize = 200;
// Initialize Three.js scene
function init() {
// Create scene
scene = new THREE.Scene();
scene.background = new THREE.Color(0x111111);
scene.fog = new THREE.FogExp2(0x111111, 0.002);
// Create camera
camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 5, 10);
// Create renderer
renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
document.getElementById('canvas-container').appendChild(renderer.domElement);
// Add lights
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(1, 1, 1);
directionalLight.castShadow = true;
scene.add(directionalLight);
// Add ground
const groundGeometry = new THREE.PlaneGeometry(worldSize, worldSize);
const groundMaterial = new THREE.MeshStandardMaterial({
color: 0x333333,
roughness: 0.8,
metalness: 0.2
});
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
ground.rotation.x = -Math.PI / 2;
ground.receiveShadow = true;
scene.add(ground);
// Add grid helper
const gridHelper = new THREE.GridHelper(worldSize, 20, 0x555555, 0x333333);
scene.add(gridHelper);
// Create simple car
createSimpleCar();
// Add world border indicator
createWorldBorder();
// Add some landmarks
createLandmarks();
// Add orbit controls for debugging
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enabled = false;
// Event listeners
window.addEventListener('resize', onWindowResize);
document.addEventListener('keydown', onKeyDown);
document.addEventListener('keyup', onKeyUp);
document.getElementById('start-btn').addEventListener('click', startDriving);
// Start animation loop
animate();
}
function createSimpleCar() {
const carGroup = new THREE.Group();
// Car body
const bodyGeometry = new THREE.BoxGeometry(3, 1.5, 6);
const bodyMaterial = new THREE.MeshStandardMaterial({ color: 0x3498db });
const body = new THREE.Mesh(bodyGeometry, bodyMaterial);
body.position.y = 0.75;
body.castShadow = true;
carGroup.add(body);
// Car cabin
const cabinGeometry = new THREE.BoxGeometry(2.5, 1, 3);
const cabinMaterial = new THREE.MeshStandardMaterial({ color: 0x2980b9 });
const cabin = new THREE.Mesh(cabinGeometry, cabinMaterial);
cabin.position.set(0, 1.5, -0.5);
carGroup.add(cabin);
// Wheels
const wheelGeometry = new THREE.CylinderGeometry(0.5, 0.5, 0.4, 16);
const wheelMaterial = new THREE.MeshStandardMaterial({ color: 0x222222 });
const wheelPositions = [
{ x: -1.5, y: 0.5, z: 2 },
{ x: 1.5, y: 0.5, z: 2 },
{ x: -1.5, y: 0.5, z: -2 },
{ x: 1.5, y: 0.5, z: -2 }
];
wheelPositions.forEach(pos => {
const wheel = new THREE.Mesh(wheelGeometry, wheelMaterial);
wheel.rotation.z = Math.PI / 2;
wheel.position.set(pos.x, pos.y, pos.z);
wheel.castShadow = true;
carGroup.add(wheel);
});
// Headlights
const headlightGeometry = new THREE.SphereGeometry(0.3, 16, 16);
const headlightMaterial = new THREE.MeshStandardMaterial({
color: 0xffffcc,
emissive: 0xffff99,
emissiveIntensity: 0.5
});
const headlight1 = new THREE.Mesh(headlightGeometry, headlightMaterial);
headlight1.position.set(-0.8, 0.8, 3);
carGroup.add(headlight1);
const headlight2 = new THREE.Mesh(headlightGeometry, headlightMaterial);
headlight2.position.set(0.8, 0.8, 3);
carGroup.add(headlight2);
// Add car to scene
carGroup.position.y = 0.5;
scene.add(carGroup);
car = carGroup;
}
function createWorldBorder() {
const borderSize = worldSize - 5;
const borderElement = document.getElementById('world-border');
borderElement.style.width = `${borderSize}px`;
borderElement.style.height = `${borderSize}px`;
borderElement.style.left = `calc(50% - ${borderSize/2}px)`;
borderElement.style.bottom = `calc(50% - ${borderSize/2}px)`;
}
function createLandmarks() {
// Portfolio section
const portfolioGeometry = new THREE.BoxGeometry(10, 2, 10);
const portfolioMaterial = new THREE.MeshStandardMaterial({
color: 0xf43f5e,
emissive: 0xf43f5e,
emissiveIntensity: 0.2
});
const portfolio = new THREE.Mesh(portfolioGeometry, portfolioMaterial);
portfolio.position.set(30, 1, 30);
portfolio.castShadow = true;
scene.add(portfolio);
// Add text to portfolio
const portfolioText = createTextMesh("PORTFOLIO", 0xffffff, 2);
portfolioText.position.set(30, 4, 30);
scene.add(portfolioText);
// About section
const aboutGeometry = new THREE.CylinderGeometry(5, 5, 2, 6);
const aboutMaterial = new THREE.MeshStandardMaterial({
color: 0x3b82f6,
emissive: 0x3b82f6,
emissiveIntensity: 0.2
});
const about = new THREE.Mesh(aboutGeometry, aboutMaterial);
about.position.set(-40, 1, -40);
about.castShadow = true;
scene.add(about);
// Add text to about
const aboutText = createTextMesh("ABOUT", 0xffffff, 2);
aboutText.position.set(-40, 4, -40);
scene.add(aboutText);
// Contact section
const contactGeometry = new THREE.SphereGeometry(5, 32, 32);
const contactMaterial = new THREE.MeshStandardMaterial({
color: 0x10b981,
emissive: 0x10b981,
emissiveIntensity: 0.2
});
const contact = new THREE.Mesh(contactGeometry, contactMaterial);
contact.position.set(-30, 5, 30);
contact.castShadow = true;
scene.add(contact);
// Add text to contact
const contactText = createTextMesh("CONTACT", 0xffffff, 2);
contactText.position.set(-30, 11, 30);
scene.add(contactText);
}
function createTextMesh(text, color, size) {
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
canvas.width = 512;
canvas.height = 256;
context.fillStyle = '#000000';
context.fillRect(0, 0, canvas.width, canvas.height);
context.font = 'Bold 80px Arial';
context.fillStyle = `rgb(${color.r * 255}, ${color.g * 255}, ${color.b * 255})`;
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText(text, canvas.width/2, canvas.height/2);
const texture = new THREE.CanvasTexture(canvas);
texture.minFilter = THREE.LinearFilter;
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.ClampToEdgeWrapping;
const material = new THREE.MeshBasicMaterial({
map: texture,
transparent: true,
side: THREE.DoubleSide
});
const geometry = new THREE.PlaneGeometry(size * (canvas.width/canvas.height) * 2, size * 2);
const mesh = new THREE.Mesh(geometry, material);
return mesh;
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
// Update world border position
const borderSize = worldSize - 5;
const borderElement = document.getElementById('world-border');
borderElement.style.left = `calc(50% - ${borderSize/2}px)`;
borderElement.style.bottom = `calc(50% - ${borderSize/2}px)`;
}
function onKeyDown(event) {
if (!isDriving) return;
switch(event.key) {
case 'ArrowUp':
speed = Math.min(speed + 0.5, maxSpeed);
break;
case 'ArrowDown':
speed = Math.max(speed - 0.5, -maxSpeed/2);
break;
case 'ArrowLeft':
car.rotation.y += 0.05;
break;
case 'ArrowRight':
car.rotation.y -= 0.05;
break;
}
}
function onKeyUp(event) {
if (!isDriving) return;
if (event.key === 'ArrowUp' || event.key === 'ArrowDown') {
// Gradual slowdown when not pressing acceleration
const slowDownInterval = setInterval(() => {
if (speed > 0) {
speed = Math.max(speed - 0.2, 0);
} else if (speed < 0) {
speed = Math.min(speed + 0.2, 0);
} else {
clearInterval(slowDownInterval);
}
}, 50);
}
}
function startDriving() {
isDriving = true;
document.getElementById('start-btn').style.display = 'none';
document.querySelector('.text-center.max-w-2xl').style.display = 'none';
// Position camera behind car
camera.position.set(0, 5, 10);
camera.lookAt(car.position);
// Enable first-person controls
controls.enabled = false;
}
function animate() {
requestAnimationFrame(animate);
if (isDriving) {
// Move car based on speed and rotation
const direction = new THREE.Vector3(0, 0, -1);
direction.applyQuaternion(car.quaternion);
car.position.add(direction.multiplyScalar(speed * 0.05));
// Update distance
distance += Math.abs(speed) * 0.01;
document.getElementById('distance').textContent = Math.floor(distance);
// Keep car within world bounds
const halfWorld = worldSize / 2 - 5;
car.position.x = THREE.MathUtils.clamp(car.position.x, -halfWorld, halfWorld);
car.position.z = THREE.MathUtils.clamp(car.position.z, -halfWorld, halfWorld);
// Update camera to follow car
const cameraOffset = new THREE.Vector3(0, 5, 10);
cameraOffset.applyQuaternion(car.quaternion);
camera.position.copy(car.position).add(cameraOffset);
camera.lookAt(car.position);
// Update speedometer
updateSpeedometer();
}
renderer.render(scene, camera);
}
function updateSpeedometer() {
const speedDisplay = document.getElementById('speed-display');
const speedNeedle = document.getElementById('speed-needle');
const absSpeed = Math.abs(Math.round(speed));
speedDisplay.textContent = absSpeed;
// Rotate needle (0km/h = -90deg, maxSpeed = 90deg)
const rotation = (absSpeed / maxSpeed) * 180 - 90;
speedNeedle.style.transform = `translateX(-50%) rotate(${rotation}deg)`;
// Change needle color based on speed
if (absSpeed > maxSpeed * 0.8) {
speedNeedle.style.background = '#ef4444';
} else if (absSpeed > maxSpeed * 0.5) {
speedNeedle.style.background = '#f59e0b';
} else {
speedNeedle.style.background = '#f43f5e';
}
}
// Start the application
init();
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=aminArtistry/ye" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>