3Dpointcloud / index.html
Harzis's picture
Upload 4 files
359ce6d verified
<!DOCTYPE html>
<html>
<head>
<script type="module" src="https://unpkg.com/@google/model-viewer/dist/model-viewer.min.js"></script>
<style>
html, body {
width: 100vw;
height: 100vh;
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.selector-panel {
background: rgba(255, 255, 255, 0.95);
padding: 2rem;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
text-align: center;
backdrop-filter: blur(10px);
max-width: 500px;
margin: 20px;
}
.selector-panel h1 {
color: #333;
margin-bottom: 1.5rem;
font-size: 1.8rem;
}
.file-option {
display: block;
width: 100%;
padding: 1rem 1.5rem;
margin: 1rem 0;
background: linear-gradient(45deg, #4facfe 0%, #00f2fe 100%);
color: white;
border: none;
border-radius: 25px;
cursor: pointer;
font-size: 1.1rem;
font-weight: bold;
transition: all 0.3s ease;
text-decoration: none;
box-shadow: 0 4px 15px rgba(79, 172, 254, 0.4);
}
.file-option:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(79, 172, 254, 0.6);
}
.file-option:active {
transform: translateY(0);
}
.file-option.secondary {
background: linear-gradient(45deg, #fa709a 0%, #fee140 100%);
box-shadow: 0 4px 15px rgba(250, 112, 154, 0.4);
}
.file-option.secondary:hover {
box-shadow: 0 6px 20px rgba(250, 112, 154, 0.6);
}
model-viewer {
width: 100vw;
height: 100vh;
display: none;
}
model-viewer.active {
display: block;
}
.back-button {
position: fixed;
top: 20px;
left: 20px;
background: rgba(255, 255, 255, 0.9);
border: none;
padding: 10px 20px;
border-radius: 25px;
cursor: pointer;
font-weight: bold;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
z-index: 1000;
display: none;
align-items: center;
gap: 8px;
}
.back-button:hover {
background: white;
transform: translateY(-1px);
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}
.back-button.active {
display: flex;
}
.back-arrow {
display: inline-block;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-right: 10px solid #333;
margin-right: 5px;
}
.file-description {
font-size: 0.9rem;
color: #666;
margin-top: 0.5rem;
}
.loading-overlay {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.8);
display: none;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 2000;
color: white;
}
.loading-spinner {
width: 50px;
height: 50px;
border: 4px solid rgba(255, 255, 255, 0.3);
border-top: 4px solid white;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-bottom: 20px;
}
.loading-text {
font-size: 1.2rem;
font-weight: bold;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="container">
<div class="selector-panel" id="selector">
<h1>Choose a 3D Model to View</h1>
<button class="file-option" onclick="loadModel('nordkapp.glb')">
Nordkapp
<div class="file-description">Machine room</div>
</button>
<button class="file-option secondary" onclick="loadModel('polarlys.glb')">
Polarlys
<div class="file-description">Machine room</div>
</button>
</div>
</div>
<button class="back-button" id="backButton" onclick="showSelector()">
<span class="back-arrow"></span>
Back to Selection
</button>
<model-viewer id="modelViewer" auto-rotate camera-controls></model-viewer>
<div class="loading-overlay" id="loadingOverlay">
<div class="loading-spinner"></div>
<div class="loading-text">Loading 3D Model...</div>
</div>
<script>
function loadModel(filename) {
const modelViewer = document.getElementById('modelViewer');
const selector = document.getElementById('selector');
const backButton = document.getElementById('backButton');
const loadingOverlay = document.getElementById('loadingOverlay');
// Show loading overlay
loadingOverlay.style.display = 'flex';
// Hide selector and show model viewer
selector.style.display = 'none';
modelViewer.classList.add('active');
backButton.classList.add('active');
// Load the selected model
modelViewer.src = filename;
// Listen for load events
modelViewer.addEventListener('load', function() {
console.log('Model loaded successfully:', filename);
loadingOverlay.style.display = 'none';
}, { once: true });
modelViewer.addEventListener('error', function(event) {
console.error('Error loading model:', filename, event);
loadingOverlay.style.display = 'none';
alert('Error loading model: ' + filename + '\nPlease check if the file exists and is valid.');
}, { once: true });
// Timeout after 240 seconds
setTimeout(() => {
if (loadingOverlay.style.display !== 'none') {
console.warn('Model loading timeout:', filename);
loadingOverlay.style.display = 'none';
alert('Loading timeout. The model file might be too large or there might be a network issue.');
}
}, 240000);
}
function showSelector() {
const modelViewer = document.getElementById('modelViewer');
const selector = document.getElementById('selector');
const backButton = document.getElementById('backButton');
// Show selector and hide model viewer
selector.style.display = 'block';
modelViewer.classList.remove('active');
backButton.classList.remove('active');
// Clear the model source
modelViewer.src = '';
}
</script>
</body>
</html>