<template>
<div ref="container" class="w-full sm:h-[30rem] lg:block hidden relative overflow-hidden">
<canvas id="canvas" ref="canvas"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref, onBeforeUnmount } from 'vue';
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
const container: { value: HTMLElement | null } = ref(null);
const canvas: { value: HTMLCanvasElement | null } = ref(null);
onMounted(() => {
if (container.value && canvas.value) {
setupWebGL(container.value, canvas.value);
}
});
function setupWebGL(container: HTMLElement, canvas: HTMLCanvasElement) {
const scene = new THREE.Scene();
const light = new THREE.AmbientLight(0xffffff, 2.8)
scene.add(light)
const camera = new THREE.PerspectiveCamera(
20,
container.clientWidth / container.clientHeight,
0.1,
200
);
camera.position.set(-4, 3, 6);
const renderer = new THREE.WebGLRenderer({
canvas,
antialias: true,
preserveDrawingBuffer: true,
alpha: true,
});
renderer.setSize(container.clientWidth, container.clientHeight);
const controls = new OrbitControls(camera, renderer.domElement);
controls.autoRotate = true;
controls.enablePan = false;
controls.enableZoom = false;
controls.maxPolarAngle = Math.PI / 2;
controls.minPolarAngle = Math.PI / 2;
const loader = new GLTFLoader();
loader.load(
'/models/planet.gltf',
(gltf) => {
gltf.scene.traverse((child) => {
if (child instanceof THREE.Mesh) {
child.material = new THREE.MeshStandardMaterial({
color: child.material.color,
map: child.material.map,
});
}
});
const earthMesh = gltf.scene;
earthMesh.scale.set(1.25, 1.25, 1.25);
scene.add(earthMesh);
animate();
},
undefined,
(error) => {
console.error('An error occurred while loading the model:', error);
}
);
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
function onWindowResize() {
camera.aspect = container.clientWidth / container.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
}
window.addEventListener('resize', onWindowResize);
onBeforeUnmount(() => {
window.removeEventListener('resize', onWindowResize);
});
}
</script>
<style scoped>
.earth-container {
width: 100%;
height: 500px;
overflow: hidden;
position: relative;
}
</style>