diff options
author | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-28 07:59:34 +0200 |
---|---|---|
committer | Zhongheng Liu <z.liu@outlook.com.gr> | 2025-01-28 07:59:34 +0200 |
commit | e23e642996e00d8138ce9035693b59c282babf69 (patch) | |
tree | c3fa115b99fa9bf9fd897760756395682051fd9a | |
parent | 8a094040e0f89d76b909d2cb694fbb8661c5025a (diff) | |
download | stvnliu.gitlab.io-e23e642996e00d8138ce9035693b59c282babf69.tar.gz stvnliu.gitlab.io-e23e642996e00d8138ce9035693b59c282babf69.tar.bz2 stvnliu.gitlab.io-e23e642996e00d8138ce9035693b59c282babf69.zip |
feat: merge 3d of old sitemerging-3d
-rw-r--r-- | app/src/App.css | 72 | ||||
-rw-r--r-- | app/src/App.tsx | 220 | ||||
-rw-r--r-- | app/src/Topbar/Topbar.tsx | 30 | ||||
-rw-r--r-- | app/src/index.tsx | 7 | ||||
-rw-r--r-- | app/src/texturemap.jpeg | bin | 0 -> 19208 bytes |
5 files changed, 250 insertions, 79 deletions
diff --git a/app/src/App.css b/app/src/App.css index 74b5e05..2fe7db2 100644 --- a/app/src/App.css +++ b/app/src/App.css @@ -1,38 +1,44 @@ -.App { - text-align: center; +body { + overflow-x: hidden; + margin: 0px; + font-family: monospace; + color: white; } - -.App-logo { - height: 40vmin; - pointer-events: none; +canvas { + position: fixed; + top: 0; + left: 0; } - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; +h1 { + font-size: 50px; +} +main { + width: 100vw; + height: 200vw; + z-index: 99; + position: absolute; justify-content: center; - font-size: calc(10px + 2vmin); - color: white; + text-align: center; + pointer-events: none; +} +section { + background: #777b7e; + border-radius: 5px; + border-color: white; + border-width: 5px; + min-height: 50vh; + padding: 25px; + margin-top: 25vh; +} +h2 { + font-size: 4vh; +} +p { + font-size: 2vh; +} +.left { + margin-right: 55%; } - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } +.right { + margin-left: 55%; } diff --git a/app/src/App.tsx b/app/src/App.tsx index b800706..a73f845 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -1,44 +1,182 @@ +import { render } from '@testing-library/react'; +import { ReactElement, useEffect, useRef } from 'react'; +import * as THREE from 'three'; +import logo from "./texturemap.jpeg"; + import './App.css'; +export const ThreeApp = (): ReactElement => { + const refContainer = useRef<HTMLDivElement>(null); + useEffect(() => { + console.log("effect running...") + const scene = new THREE.Scene(); + scene.background = new THREE.Color(0x000000) + scene.backgroundIntensity = 0.2 + const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); + const renderer = new THREE.WebGLRenderer(); + renderer.setSize(window.innerWidth, window.innerHeight); + window.onresize = () => { + camera.aspect = window.innerWidth / window.innerHeight + camera.updateProjectionMatrix() + renderer.setSize(window.innerWidth, window.innerHeight) + renderer.render(scene, camera) + } + // render objects + const geometry = new THREE.BoxGeometry(2, 2, 2); + const material = new THREE.MeshStandardMaterial({}); + material.map = new THREE.TextureLoader().load(logo) + const cube = new THREE.Mesh(geometry, material); + const ambientLight = new THREE.AmbientLight(0xffffff, 1); + const directionalLight = new THREE.DirectionalLight(0xffffff, 1) + scene.add(directionalLight) + scene.add(ambientLight) + scene.add(cube); + document.body.appendChild(renderer.domElement); -function App() { - return ( - <div className="App"> - <div className="aboutme"> - <h1>Zhongheng Liu</h1> - <p>-- Web developer and GNU/Linux enthusiast.</p> - <button onClick={() => { window.location.assign("/assets/resume.pdf"); }}>Learn more</button> - <button onClick={() => { window.location.assign("https://gitlab.com/stvnliu"); }}>My GitLab</button> - </div> - <div className="projects"> - <h1>My projects</h1> - <p>These are mostly hobbyist programming projects</p> - <hr></hr> - <h3><a href='https://gitlab.com/stvnliu/proteinpedia-next'> - proteinpedia-next - </a> - </h3> - <p>A content management platform for displaying and managing informatio - n of proteins and other chemical</p> - <hr></hr> - <h3><a href="/assets/paper.pdf">How can privacy and web inter-connectivity be - enshrined as core principles in self-hosted online chat applications? - </a></h3> - <p>An Edexcel Level 3 Artifact Extended Project Qualification (EPQ) on - the topic of web chat applications, awarded an A* grade by Edexcel</p> - <p>You may find the relevant GitLab repositories here:</p> - <span> - GitHub repositories for - <a href="https://github.com/stvnliu/epq-web">web</a> and - <a href="https://github.com/stvnliu/epq-api">backend API</a> - </span><br /> - <span> - GitLab repository for - <a href="https://gitlab.com/stvnliu/epq-web">web</a> and - <a href="https://gitlab.com/stvnliu/epq-api">backend API</a> - </span> - </div> - </div> - ); -} + camera.position.z = 5; + camera.position.y = 2; + camera.lookAt(cube.position) + + // progressive animation through scrolling + function lerp(x: number, y: number, a: number): number { + return (1 - a) * x + a * y + } + function scalePercent(start: number, end: number) { + return (scrollPercent - start) / (end - start) + } + const animationKeyframes: { start: number; end: number; func: () => void }[] = [] + + animationKeyframes.push({ + start: 0, + end: 15, + func: () => { + camera.lookAt(cube.position.x - 5, cube.position.y, cube.position.z - 10) + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + cube.position.z = lerp(0, 5, scalePercent(0, 15)) + cube.position.x = lerp(10, -10, scalePercent(0, 15)) + + //console.log(cube.position.z) + }, + }) + animationKeyframes.push({ + start: 15, + end: 30, + func: () => { + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + camera.lookAt(cube.position.x - 5, cube.position.y, cube.position.z - 10) + //console.log(cube.rotation.z) + }, + }) + animationKeyframes.push({ + start: 30, + end: 45, + func: () => { + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + camera.position.x = lerp(0, 5, scalePercent(30, 45)) + camera.position.z = lerp(5, -5, scalePercent(30, 45)) + camera.lookAt(lerp(cube.position.x - 5, cube.position.x + 10, scalePercent(30, 45)), cube.position.y, lerp(cube.position.z - 10, cube.position.z + 10, scalePercent(30, 45))) + //console.log(camera.position.x + " " + camera.position.y) + }, + }) + animationKeyframes.push({ + start: 45, + end: 60, + func: () => { + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + camera.lookAt(cube.position.x + 10, cube.position.y, cube.position.z + 10) + //console.log(cube.rotation.z) + }, + }) + animationKeyframes.push({ + start: 60, + end: 70, + func: () => { + //auto rotate + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + cube.position.x = lerp(-10, 20, scalePercent(60, 70)) + camera.lookAt(lerp(cube.position.x + 10, cube.position.x - 10, scalePercent(60, 70)), cube.position.y, cube.position.z + 10) + }, + }) + animationKeyframes.push({ + start: 70, + end: 80, + func: () => { + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + camera.lookAt(cube.position.x - 10, cube.position.y, cube.position.z + 10) + }, + }) + animationKeyframes.push({ + start: 80, + end: 101, + func: () => { + cube.rotation.x += 0.01 + cube.rotation.y += 0.01 + cube.position.x = lerp(20, -5, scalePercent(80, 100)) + camera.lookAt(lerp(cube.position.x - 10, cube.position.x + 10, scalePercent(80, 101)), cube.position.y, cube.position.z + 10) + }, + }) + + function playScrollAnimations() { + animationKeyframes.forEach((a) => { + if (scrollPercent >= a.start && scrollPercent < a.end) { + a.func() + } + }) + } -export default App; + let scrollPercent = 0 + window.onscroll = () => { + scrollPercent = + ((document.documentElement.scrollTop || document.body.scrollTop) / + ((document.documentElement.scrollHeight || + document.body.scrollHeight) - + document.documentElement.clientHeight)) * + 100; + } + + function animate() { + requestAnimationFrame(animate); + playScrollAnimations() + renderer.render(scene, camera); + } + window.scrollTo({ top: 0, behavior: 'smooth' }) + animate(); + }, []) + + return ( + <main ref={refContainer}> + <h1>Website Under Construction</h1> + <section className='left'> + <h2>Steven Liu</h2> + <p>I write sometimes-functional code in JavaScript React, Java, and a bit of Python.</p> + </section> + <section className='right'> + <h2>Changing Objects Position</h2> + <p>The cubes position is now changing</p> + </section> + + <section className='left'> + <h2>Changing Objects Rotation</h2> + <p>The cubes rotation is now changing</p> + </section> + + <section className='right'> + <h2>Changing Camera Position</h2> + <p>The camera position is now changing</p> + </section> + + <section className='left'> + <h2>You are at the bottom</h2> + <p>The cube will now be auto rotating</p> + <p> + Now you can scroll back to the top to reverse the animation + </p> + </section> + </main> + ) +} diff --git a/app/src/Topbar/Topbar.tsx b/app/src/Topbar/Topbar.tsx new file mode 100644 index 0000000..14ef0ec --- /dev/null +++ b/app/src/Topbar/Topbar.tsx @@ -0,0 +1,30 @@ +export const Topbar = (): React.ReactElement => { + return (<nav className="navbar navbar-expand-sm navbar-light bg-light"> + <a className="navbar-brand" href="#">Navbar</a> + <button className="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId" aria-controls="collapsibleNavId" + aria-expanded="false" aria-label="Toggle navigation"> + <span className="navbar-toggler-icon"></span> + </button> + <div className="collapse navbar-collapse" id="collapsibleNavId"> + <ul className="navbar-nav mr-auto mt-2 mt-lg-0"> + <li className="nav-item active"> + <a className="nav-link" href="#">Home <span className="sr-only">(current)</span></a> + </li> + <li className="nav-item"> + <a className="nav-link" href="#">Link</a> + </li> + <li className="nav-item dropdown"> + <a className="nav-link dropdown-toggle" href="#" id="dropdownId" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Dropdown</a> + <div className="dropdown-menu" aria-labelledby="dropdownId"> + <a className="dropdown-item" href="#">Action 1</a> + <a className="dropdown-item" href="#">Action 2</a> + </div> + </li> + </ul> + <form className="form-inline my-2 my-lg-0"> + <input className="form-control mr-sm-2" type="text" placeholder="Search" /> + <button className="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button> + </form> + </div> + </nav>) +};
\ No newline at end of file diff --git a/app/src/index.tsx b/app/src/index.tsx index 032464f..6a6998b 100644 --- a/app/src/index.tsx +++ b/app/src/index.tsx @@ -1,16 +1,13 @@ import React from 'react'; import ReactDOM from 'react-dom/client'; -import './index.css'; -import App from './App'; import reportWebVitals from './reportWebVitals'; +import { ThreeApp } from './App'; const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( - <React.StrictMode> - <App /> - </React.StrictMode> + <ThreeApp /> ); // If you want to start measuring performance in your app, pass a function diff --git a/app/src/texturemap.jpeg b/app/src/texturemap.jpeg Binary files differnew file mode 100644 index 0000000..c9e65e0 --- /dev/null +++ b/app/src/texturemap.jpeg |