118 lines
2.5 KiB
Svelte
118 lines
2.5 KiB
Svelte
<script lang="ts">
|
|
import { beforeUpdate, afterUpdate, onMount, onDestroy } from 'svelte';
|
|
import * as Three from 'three';
|
|
|
|
export let width: number;
|
|
export let height: number;
|
|
|
|
//#region variables
|
|
let container: HTMLElement;
|
|
let canvas: HTMLCanvasElement;
|
|
let maxInnerWidth: number = 0;
|
|
let maxInnerHeight: number = 0;
|
|
|
|
let portrait: boolean = true;
|
|
let focalLength: number = 540 / Math.atan((70 * Math.PI) / 180);
|
|
let fov = 75;
|
|
//let baseHorizontalFOV: number = 2.0*Math.atan(baseAspectRation*Math.tan(baseVerticalFOV*0.5));
|
|
|
|
let scene: Three.Scene = new Three.Scene();
|
|
let camera: Three.PerspectiveCamera = new Three.PerspectiveCamera(
|
|
75,
|
|
1,
|
|
0.1,
|
|
1000,
|
|
);
|
|
|
|
let renderer: Three.WebGLRenderer = new Three.WebGLRenderer();
|
|
let box: Three.BoxGeometry = new Three.BoxGeometry(1, 1, 1);
|
|
let mat: Three.MeshBasicMaterial = new Three.MeshBasicMaterial({
|
|
color: 0x00ff00,
|
|
});
|
|
let cube = new Three.Mesh(box, mat);
|
|
//#endregion
|
|
|
|
//#region functions
|
|
function updateVerticalFOV() {
|
|
fov = (180 / Math.PI) * Math.tan(innerHeight / (focalLength * 2));
|
|
}
|
|
|
|
function resetMaxDimensions() {
|
|
maxInnerWidth = 0;
|
|
maxInnerHeight = 0;
|
|
}
|
|
|
|
function updateMaxInnerDimensions() {
|
|
if (maxInnerWidth < width) {
|
|
maxInnerWidth = width;
|
|
}
|
|
if (maxInnerHeight < height) {
|
|
maxInnerHeight = height;
|
|
}
|
|
}
|
|
|
|
function checkOrientation(oldPortrait: boolean) {
|
|
if (innerWidth > height) {
|
|
portrait = false;
|
|
} else {
|
|
portrait = true;
|
|
}
|
|
|
|
if (oldPortrait != portrait) {
|
|
resetMaxDimensions();
|
|
}
|
|
}
|
|
|
|
function animate() {
|
|
requestAnimationFrame(animate);
|
|
|
|
cube.rotation.x += 0.05;
|
|
cube.rotation.y += 0.05;
|
|
|
|
renderer.render(scene, camera);
|
|
}
|
|
//#endregion
|
|
|
|
onMount(() => {
|
|
canvas = container.appendChild(renderer.domElement);
|
|
|
|
scene.add(cube);
|
|
|
|
camera.position.z = 5;
|
|
|
|
animate();
|
|
});
|
|
|
|
beforeUpdate(() => {
|
|
checkOrientation(portrait);
|
|
updateMaxInnerDimensions();
|
|
updateVerticalFOV();
|
|
|
|
camera.aspect = width / height;
|
|
camera.fov = fov;
|
|
camera.setViewOffset(width, height, 0, 0, width, height);
|
|
renderer.setSize(width, height);
|
|
|
|
renderer.setClearColor(0x000000, 0.1);
|
|
});
|
|
|
|
afterUpdate(() => {});
|
|
|
|
onDestroy(() => {
|
|
container.removeChild(canvas);
|
|
});
|
|
</script>
|
|
|
|
<div class="Container" bind:this={container} />
|
|
|
|
<style>
|
|
.Container {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: hidden;
|
|
}
|
|
</style>
|