From ee6db61567184682aaee728ebc610e05cc75c6a4 Mon Sep 17 00:00:00 2001 From: Cdm2883 Date: Wed, 22 Jan 2025 16:33:58 +0800 Subject: [PATCH] feat: model interaction --- website/src/assets/javascripts/main.ts | 67 +++++++++--------------- website/src/assets/stylesheets/main.scss | 11 +++- 2 files changed, 34 insertions(+), 44 deletions(-) diff --git a/website/src/assets/javascripts/main.ts b/website/src/assets/javascripts/main.ts index e9a48a4..a7503df 100644 --- a/website/src/assets/javascripts/main.ts +++ b/website/src/assets/javascripts/main.ts @@ -1,10 +1,10 @@ import * as THREE from "three"; import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; +import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"; const image = document.querySelector('#index-page .logo img'); const canvas = document.querySelector('#index-page .logo canvas'); const logoBox = document.querySelector('#index-page .logo-box'); -const titleBox = document.querySelector('#index-page .title'); const animationStart = Date.now(); let animationDone = false; @@ -12,7 +12,7 @@ logoBox.addEventListener('animationend', _ => setTimeout(() => animationDone = true, (Date.now() - animationStart) * 1.3)); const scene = new THREE.Scene(); -const camera = new THREE.PerspectiveCamera(60, 1, 0.1, 80); +const camera = new THREE.PerspectiveCamera(60, 1, 0.01, 100); const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, canvas }); const deg = THREE.MathUtils.degToRad(1) @@ -22,10 +22,14 @@ renderer.setClearAlpha(0); const ambientLight = new THREE.AmbientLight(0xFFFFFF, 10); scene.add(ambientLight); +const controls = new OrbitControls(camera, renderer.domElement); +controls.enableDamping = true; + const loader = new GLTFLoader(); let logo: THREE.Object3D; loader.load("./assets/models/logo.glb", data => { logo = data.scene; + logo.remove(logo.getObjectByName('node_3')); logo.rotation.y = -90 * deg; scene.add(logo); @@ -36,10 +40,27 @@ loader.load("./assets/models/logo.glb", data => { let currentRotationY = 0; function animate() { if (logo) logo.rotation.y = (-90 + currentRotationY) * deg; + controls.update(); renderer.render(scene, camera); requestAnimationFrame(animate); } +let canvasActiveTimer = null; +const canvasActive = () => { + canvas.classList.add('active-animation'); + canvas.classList.add('active'); + if (canvasActiveTimer) clearTimeout(canvasActiveTimer); + canvasActiveTimer = setTimeout(() => canvas.classList.remove("active"), 3000); +}; +canvas.addEventListener('touchstart', canvasActive); +canvas.addEventListener('touchmove', canvasActive); +let mouseDown = false; +// @ts-ignore +canvas.addEventListener('mousedown', () => mouseDown = canvasActive() || true); +canvas.addEventListener('mouseup', () => mouseDown = false); +canvas.addEventListener('mousemove', () => mouseDown && canvasActive()); +canvas.addEventListener('wheel', canvasActive); + function postShowCanvas() { if (animationDone) showCanvas(); else setTimeout(postShowCanvas, 100); @@ -48,46 +69,6 @@ function showCanvas() { image.classList.toggle("hide"); canvas.classList.toggle("hide"); const { clientWidth, clientHeight } = renderer.domElement; - const [ width, height ] = [clientWidth * devicePixelRatio, clientHeight * devicePixelRatio]; + const [ width, height ] = [ clientWidth * devicePixelRatio, clientHeight * devicePixelRatio ]; renderer.setSize(width, height, false); } - - - -const bezier = cubicBezier(1, -0.54, 0, 1.54); -const autoRotation = setInterval(() => { - if (!animationDone) return; - const endN = 300; - let n = 0; - const timer = setInterval(() => - // @ts-ignore - currentRotationY = ++n >= endN ? clearInterval(timer) || 0 : 360 * bezier(n / endN), 1); -}, 5000); - -function cubicBezier(x1: number, y1: number, x2: number, y2: number): (t: number) => number { - const bezier = (t: number, p0: number, p1: number, p2: number, p3: number) => { - const u = 1 - t; - return u * u * u * p0 + 3 * u * u * t * p1 + 3 * u * t * t * p2 + t * t * t * p3; - } - const solveX = (t: number) => bezier(t, 0, x1, x2, 1); - const solveY = (t: number) => bezier(t, 0, y1, y2, 1); - return function(t: number) { - let left = 0; - let right = 1; - const epsilon = 0.0001; - let x = solveX(t); - - while (right - left > epsilon) { - let mid = (left + right) / 2; - let xMid = solveX(mid); - if (xMid < x) { - left = mid; - } else { - right = mid; - } - } - - let resultT = (left + right) / 2; - return solveY(resultT); - }; -} diff --git a/website/src/assets/stylesheets/main.scss b/website/src/assets/stylesheets/main.scss index fefba0f..805b811 100644 --- a/website/src/assets/stylesheets/main.scss +++ b/website/src/assets/stylesheets/main.scss @@ -4,6 +4,7 @@ } $text-color: #ececec; +$accent-red: #cc0000; html { color: $text-color; background-color: #1e1f22; @@ -128,6 +129,14 @@ $logo-box-end: min(80vmin, 500px); .hide { opacity: 0; } + canvas.active-animation { + background-color: transparent; + transition: background-color ease .2s; + } + canvas.active { + //background-color: $accent-red; + background-color: black; + } } .decoration { @@ -254,7 +263,7 @@ $logo-box-end: min(80vmin, 500px); $size: relative-size(30); width: $size; height: $size; - background: #cc0000; + background: $accent-red; } } .sub {