mirror of
https://github.com/TomHodson/tomhodson.github.com.git
synced 2025-06-26 10:01:18 +02:00
178 lines
5.7 KiB
JavaScript
178 lines
5.7 KiB
JavaScript
import * as THREE from "three";
|
|
|
|
// import * as dat from 'dat.gui';
|
|
|
|
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
|
import { DRACOLoader } from "three/addons/loaders/DRACOLoader.js";
|
|
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
|
import { EffectComposer } from "three/addons/postprocessing/EffectComposer.js";
|
|
import { RenderPass } from "three/addons/postprocessing/RenderPass.js";
|
|
import { ShaderPass } from "three/addons/postprocessing/ShaderPass.js";
|
|
import { FXAAShader } from "three/addons/shaders/FXAAShader.js";
|
|
import { Timer } from "three/addons/Addons.js";
|
|
|
|
import { setupThreeJS, serialiseCamera } from "./helpers.js";
|
|
import { CustomOutlinePass } from "./CustomOutlinePass.js";
|
|
import FindSurfaces from "./FindSurfaces.js";
|
|
|
|
import { load_gltf } from "./LoadGLTF.js";
|
|
|
|
// let ticking = false;
|
|
// let attached = false;
|
|
// function render() {
|
|
// const there =
|
|
// viewer.getBoundingClientRect().bottom <
|
|
// sticky.getBoundingClientRect().bottom;
|
|
|
|
// const delta = (window.scrollY - last_scroll_pos) / 30;
|
|
|
|
// if (there && !attached) {
|
|
// console.log("attaching");
|
|
// sticky.appendChild(viewer);
|
|
// viewer.hide_ui();
|
|
// viewer.style.height = "100px";
|
|
// viewer.style.width = "100px";
|
|
// viewer.style["min-height"] = "unset";
|
|
// viewer.component.canvas.style.height = "100%";
|
|
// viewer.style.border = "unset";
|
|
// viewer.onWindowResize();
|
|
// viewer.component.render_loop = false;
|
|
// attached = true;
|
|
// }
|
|
|
|
// if ((window.scrollY < transition_scroll_pos) && attached) {
|
|
// console.log("detaching");
|
|
// viewer.replaceWith(date);
|
|
// byline.style.display = "unset";
|
|
// attached = false;
|
|
// }
|
|
|
|
export class ScrollLockedViewer extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.shadow = this.attachShadow({ mode: "open" });
|
|
}
|
|
|
|
connectedCallback() {
|
|
let component = setupThreeJS(this);
|
|
this.component = component;
|
|
const { canvas, camera, scene, renderer } = component;
|
|
|
|
component.hide_ui();
|
|
this.style.display = "block";
|
|
// this.style.height = "100px";
|
|
this.style["aspect-ratio"] = "1 / 1";
|
|
this.style["min-height"] = "unset";
|
|
component.canvas.style.height = "100%";
|
|
component.container.style.height = "100%";
|
|
// this.style.border = "unset";
|
|
|
|
const render_size_multiplier = 4;
|
|
renderer.setPixelRatio(render_size_multiplier);
|
|
renderer.setSize(canvas.clientWidth, canvas.clientHeight, false);
|
|
|
|
const model_path = this.getAttribute("model");
|
|
const spin = (this.getAttribute("spin") || "true") === "true";
|
|
|
|
// determine the outline and bg colors
|
|
const body = document.getElementsByTagName("body")[0];
|
|
const style = window.getComputedStyle(body);
|
|
const outline_color = style.getPropertyValue("--theme-model-line-color");
|
|
const model_color = style.getPropertyValue("--theme-model-bg-color");
|
|
|
|
const directionalLight = new THREE.DirectionalLight(
|
|
0xffffff,
|
|
this.getAttribute("directional-light") || 2
|
|
);
|
|
scene.add(directionalLight);
|
|
directionalLight.position.set(1.7, 1, -1);
|
|
|
|
const ambientLight = new THREE.AmbientLight(
|
|
0xffffff,
|
|
this.getAttribute("ambient-light") || 0.5
|
|
);
|
|
scene.add(ambientLight);
|
|
|
|
// Set up post processing
|
|
// Create a render target that holds a depthTexture so we can use it in the outline pass
|
|
// See: https://threejs.org/docs/index.html#api/en/renderers/WebGLRenderTarget.depthBuffer
|
|
console.log(`clientHeight ${canvas.clientHeight} height ${canvas.height}`);
|
|
console.log(`clientWidth ${canvas.clientWidth} width ${canvas.width}`);
|
|
const depthTexture = new THREE.DepthTexture();
|
|
const renderTarget = new THREE.WebGLRenderTarget(
|
|
canvas.width,
|
|
canvas.height,
|
|
{
|
|
depthTexture: depthTexture,
|
|
depthBuffer: true,
|
|
}
|
|
);
|
|
|
|
// Initial render pass.
|
|
const composer = new EffectComposer(renderer, renderTarget);
|
|
component.composer = composer;
|
|
const pass = new RenderPass(scene, camera);
|
|
composer.addPass(pass);
|
|
|
|
// Outline pass.
|
|
const customOutline = new CustomOutlinePass(
|
|
new THREE.Vector2(canvas.width, canvas.height),
|
|
scene,
|
|
camera,
|
|
outline_color,
|
|
render_size_multiplier
|
|
);
|
|
composer.addPass(customOutline);
|
|
|
|
// Antialias pass.
|
|
// const effectFXAA = new ShaderPass(FXAAShader);
|
|
// effectFXAA.uniforms["resolution"].value.set(
|
|
// 1.0 / canvas.width,
|
|
// 1.0 / canvas.height
|
|
// );
|
|
// composer.addPass(effectFXAA);
|
|
|
|
// Load model
|
|
const loader = new GLTFLoader();
|
|
const dracoLoader = new DRACOLoader();
|
|
dracoLoader.setDecoderConfig({ type: "js" });
|
|
dracoLoader.setDecoderPath("https://www.gstatic.com/draco/v1/decoders/");
|
|
loader.setDRACOLoader(dracoLoader);
|
|
const surfaceFinder = new FindSurfaces();
|
|
loader.load(model_path, (gltf) =>
|
|
load_gltf(this, scene, surfaceFinder, model_color, customOutline, gltf)
|
|
);
|
|
|
|
// Set up orbital camera controls.
|
|
let controls = new OrbitControls(camera, renderer.domElement);
|
|
component.controls = controls;
|
|
controls.autoRotate = spin;
|
|
controls.update();
|
|
|
|
let last_scroll_pos = 0;
|
|
const onscroll = () => {
|
|
const delta = (window.scrollY - last_scroll_pos) / 30;
|
|
|
|
if (Math.abs(delta) > 0.1) {
|
|
controls.update(delta);
|
|
composer.render();
|
|
last_scroll_pos = window.scrollY;
|
|
}
|
|
};
|
|
|
|
let ticking = false;
|
|
document.addEventListener("scroll", (event) => {
|
|
if (!ticking) {
|
|
window.requestAnimationFrame(() => {
|
|
onscroll();
|
|
ticking = false;
|
|
});
|
|
ticking = true;
|
|
}
|
|
});
|
|
this.render = composer.render;
|
|
}
|
|
}
|
|
|
|
export default ScrollLockedViewer;
|