This commit is contained in:
Tben 2022-03-11 11:43:00 +01:00
parent a7d863d5c4
commit 6646654de0
13 changed files with 2818 additions and 5858 deletions

View File

@ -0,0 +1,151 @@
import * as THREE from "three";
export default function threeJsAnimations() {
const animationWrapper = document.getElementById("homepage-animation-wrapper");
console.log(THREE);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, animationWrapper.clientWidth / animationWrapper.clientHeight, 0.1, 1000);
const light = new THREE.PointLight(0xff0000, 1, 200);
light.position.set(-1, -1, 5);
const ambientLight = new THREE.AmbientLight("#adb2d3");
const pointLight = new THREE.PointLight(0xffffff, 1, 100);
pointLight.position.set(10, 10, 10);
const sphereSize = 1;
const pointLightHelper = new THREE.PointLightHelper(pointLight, sphereSize);
// const spotLight = new THREE.SpotLight(0xffffff);
// spotLight.position.set(10, 10, 10);
// scene.add(spotLight);
// const spotLightHelper = new THREE.SpotLightHelper(spotLight);
// scene.add(spotLightHelper);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(animationWrapper.clientWidth, animationWrapper.clientHeight);
animationWrapper.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshPhongMaterial({
// light
// specular: "rgb(30, 33, 68)",
// intermediate
color: "rgb(30, 33, 68)",
// dark
// emissive: "rgb(30, 33, 68)",
shininess: 50,
wireframe: true,
// map: THREE.ImageUtils.loadTexture("http://i.imgur.com/xCE2Br4.jpg?1"),
});
const cube = new THREE.Mesh(geometry, material);
const material2 = new THREE.MeshPhongMaterial({
// light
// specular: "rgb(30, 33, 68)",
// intermediate
color: "#1668e4",
// dark
// emissive: "rgb(30, 33, 68)",
shininess: 50,
wireframe: false,
// map: THREE.ImageUtils.loadTexture("http://i.imgur.com/xCE2Br4.jpg?1"),
});
const cube2 = new THREE.Mesh(geometry, material2);
cube2.position.x = window.innerWidth > 500 ? 1.5 : -0.5;
cube2.position.y = window.innerWidth > 500 ? 1.5 : 1.8;
cube2.position.z = -1;
cube2.scale.x = 0.3;
cube2.scale.y = 0.3;
cube2.scale.z = 0.3;
const material3 = new THREE.MeshPhongMaterial({
// light
// specular: "rgb(30, 33, 68)",
// intermediate
color: "rgb(53, 65, 194)",
// dark
// emissive: "rgb(30, 33, 68)",
shininess: 50,
wireframe: false,
// map: THREE.ImageUtils.loadTexture("http://i.imgur.com/xCE2Br4.jpg?1"),
});
const cube3 = new THREE.Mesh(geometry, material3);
scene.add(cube);
scene.add(cube2);
scene.add(cube3);
scene.add(ambientLight);
scene.add(light);
scene.add(pointLight);
scene.add(pointLightHelper);
cube3.position.x = -1.5;
cube3.position.y = -1.5;
cube3.position.z = -1;
cube3.scale.x = 0.2;
cube3.scale.y = 0.2;
cube3.scale.z = 0.2;
camera.position.z = 2;
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
cube.rotation.x += 0.002;
cube.rotation.y += 0.002;
cube2.rotation.x += 0.005;
cube2.rotation.y += 0.005;
cube3.rotation.x += 0.01;
cube3.rotation.y += 0.01;
scene.rotation.z += 0.0003;
}
animate();
window.addEventListener("mousemove", (e) => {
let relMouseX = e.x - window.innerWidth / 2;
let relMouseY = e.y - window.innerHeight / 2;
// console.log("X pos: ", relMouseX);
// console.log("Y pos: ", relMouseY);
// console.log(e.y);
relMouseX < 0 ? (cube.rotation.x += 0.003) : (cube.rotation.x += 0.003);
relMouseY > 0 ? (cube.rotation.y += 0.003) : (cube.rotation.y += 0.003);
relMouseX < 0 ? (cube2.position.x += 0.001) : (cube2.position.x -= 0.001);
relMouseY > 0 ? (cube2.position.y += 0.001) : (cube2.position.y -= 0.001);
relMouseX < 0 ? (cube3.position.x += 0.0007) : (cube3.position.x -= 0.0007);
relMouseY > 0 ? (cube3.position.y += 0.0007) : (cube3.position.y -= 0.0007);
// relMouseX < 0 ? scene.rotateX(5) : scene.rotateX(-5);
// relMouseY > 0 ? scene.rotateX(5) : scene.rotateX(-5);
// relMouseX < 0 ? (scene.rotation.z += 0.005) : (scene.rotation.x += 0.005);
// relMouseY > 0 ? (scene.rotation.y += 0.005) : (scene.rotation.y += 0.005);
// cube.rotation.x += relMouseX / e.x;
// cube.rotation.y += relMouseY / e.y;
// scene.rotation.x;
});
window.addEventListener("resize", (e) => {
renderer.setSize(animationWrapper.clientWidth, window.innerHeight);
// animationWrapper.querySelector("canvas").width = animationWrapper.clientWidth;
// animationWrapper.querySelector("canvas").height = animationWrapper.clientHeight;
});
window.addEventListener("scroll", (e) => {
if (window.scrollY > 100) {
scene.remove(cube2);
scene.remove(cube3);
} else {
scene.add(cube2);
scene.add(cube3);
}
});
}

View File

@ -1,11 +1,11 @@
import React, { Fragment } from 'react' import React, { Fragment } from 'react';
import GeneralHeader from './GeneralHeader' import GeneralHeader from './GeneralHeader';
const GeneralLayout = ({children}) => { const GeneralLayout = ({ children }) => {
return ( return (
<Fragment> <Fragment>
<GeneralHeader/> <GeneralHeader />
{children} { children }
</Fragment> </Fragment>
) )
} }

8244
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,32 +1,37 @@
{ {
"name": "personal_site", "name": "personal_site",
"version": "1.0.0", "version": "1.0.0",
"description": "My personal site", "description": "My personal site",
"main": "index.js", "main": "index.js",
"directories": { "directories": {
"doc": "docs" "doc": "docs"
}, },
"scripts": { "scripts": {
"dev": "next dev -p 5000", "dev": "next dev -p 5000",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint",
}, "tailwind": "npx tailwindcss -i ./tailwind/tw_main.css -o ./styles/tw_main.css --watch"
"repository": { },
"type": "git", "repository": {
"url": "git+https://github.com/BenjaminToby/personal_site.git" "type": "git",
}, "url": "git+https://github.com/BenjaminToby/personal_site.git"
"keywords": [], },
"author": "", "keywords": [],
"license": "ISC", "author": "",
"bugs": { "license": "ISC",
"url": "https://github.com/BenjaminToby/personal_site/issues" "bugs": {
}, "url": "https://github.com/BenjaminToby/personal_site/issues"
"homepage": "https://github.com/BenjaminToby/personal_site#readme", },
"dependencies": { "homepage": "https://github.com/BenjaminToby/personal_site#readme",
"next": "^12.0.4", "dependencies": {
"nodemailer": "^6.7.2", "next": "^12.0.4",
"react": "^17.0.2", "nodemailer": "^6.7.2",
"react-dom": "^17.0.2" "react": "^17.0.2",
} "react-dom": "^17.0.2",
"three": "^0.138.3"
},
"devDependencies": {
"tailwindcss": "^3.0.23"
}
} }

View File

@ -1,4 +1,5 @@
import "../styles/main.css"; import "../styles/main.css";
import "../styles/tw_main.css";
import { Fragment } from "react"; import { Fragment } from "react";
import Script from "next/script"; import Script from "next/script";

View File

@ -2,8 +2,13 @@ import React from 'react'
import Head from 'next/head' import Head from 'next/head'
import TextShuffler from '../components/actions/TextShuffler' import TextShuffler from '../components/actions/TextShuffler'
import GeneralLayout from '../layouts/general_layout/GeneralLayout' import GeneralLayout from '../layouts/general_layout/GeneralLayout'
import threeJsAnimations from '../functions/frontend/threeJsAnimations'
const about = () => { const about = () => {
React.useEffect(() => {
threeJsAnimations()
}, [])
return ( return (
<GeneralLayout> <GeneralLayout>
<Head> <Head>
@ -12,12 +17,13 @@ const about = () => {
</Head> </Head>
<h1><TextShuffler textInput="Ben of all trade, master of all!" /></h1> <h1><TextShuffler textInput="Ben of all trade, master of all!" /></h1>
<span className='hero-sub-text'> <span className='hero-sub-text'>
<TextShuffler textInput="So the thing about me is: I want to know it all, I want to master it all: this has lead me to dig deep into almost every aspect of web design and development. But that's not the best thing about me: the best thing is I'm willing to learn and adapt at any point: there are so many languages and libraries these days: even in my quest to master it all, it is not possible to master all the available languages and libraries: but whichever knowledge is needed at any given time, I adapt and learn: very quickly too: I see this as the best skill anyone can have in this age." /> <TextShuffler textInput="So the thing about me is: I want to know it all, I want to master it all: hence I've dug deep into almost every aspect of web design and development. In the process I've developed my most valuable skill: learnabiltiy: there are so many languages and libraries out there: about a dozen different ways to achieve the same result: even in my quest to master it all, it is not possible to master all the available languages, libraries and other web technologies: but whichever knowledge is needed at any given time, I adapt and learn: very quickly." />
</span> </span>
<div className="hero-ctas-section"> <div className="hero-ctas-section">
<a href='/documents/Benjamin_Toby_CV.pdf' download={true}>See my resume</a> <a href='/documents/Benjamin_Toby_CV.pdf' download={ true }>See my resume</a>
<a href='https://www.linkedin.com/in/benjamin-toby/' target="_blank">Linkedin</a> <a href='https://www.linkedin.com/in/benjamin-toby/' target="_blank">Linkedin</a>
</div> </div>
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
</GeneralLayout> </GeneralLayout>
) )
} }

View File

@ -3,11 +3,17 @@ import Head from 'next/head'
import TextShuffler from '../components/actions/TextShuffler' import TextShuffler from '../components/actions/TextShuffler'
import submitContactForm from '../functions/frontend/submitContactForm' import submitContactForm from '../functions/frontend/submitContactForm'
import GeneralLayout from '../layouts/general_layout/GeneralLayout' import GeneralLayout from '../layouts/general_layout/GeneralLayout'
import threeJsAnimations from '../functions/frontend/threeJsAnimations'
const contact = () => { const contact = () => {
let [success, setSuccess] = React.useState(false); let [success, setSuccess] = React.useState(false);
React.useEffect(() => {
threeJsAnimations()
}, [])
return ( return (
<GeneralLayout> <GeneralLayout>
<Head> <Head>
@ -28,6 +34,7 @@ const contact = () => {
{ success === "Success" && <div className='message-response'>Success!!! <button onClick={ () => { window.location.reload() } }>Reload</button></div> } { success === "Success" && <div className='message-response'>Success!!! <button onClick={ () => { window.location.reload() } }>Reload</button></div> }
{ success === "Failed" && <div className='message-response failed'>Failed <button onClick={ () => { window.location.reload() } }>Reload</button></div> } { success === "Failed" && <div className='message-response failed'>Failed <button onClick={ () => { window.location.reload() } }>Reload</button></div> }
</form> </form>
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
</GeneralLayout> </GeneralLayout>
) )
} }

View File

@ -1,9 +1,13 @@
import Head from 'next/head' import Head from 'next/head'
import React from 'react' import React from 'react'
import TextShuffler from '../components/actions/TextShuffler' import TextShuffler from '../components/actions/TextShuffler'
import threeJsAnimations from '../functions/frontend/threeJsAnimations'
import GeneralLayout from '../layouts/general_layout/GeneralLayout' import GeneralLayout from '../layouts/general_layout/GeneralLayout'
const index = () => { const index = () => {
React.useEffect(() => {
threeJsAnimations()
}, [])
return ( return (
<GeneralLayout> <GeneralLayout>
<Head> <Head>
@ -15,9 +19,10 @@ const index = () => {
<TextShuffler textInput="Hi, I'm Benjamin Toby, a highly talented fullstack web developer with extensive enxperience in web design, frontend and backend development." /> <TextShuffler textInput="Hi, I'm Benjamin Toby, a highly talented fullstack web developer with extensive enxperience in web design, frontend and backend development." />
</span> </span>
<div className="hero-ctas-section"> <div className="hero-ctas-section">
<a href='/documents/Benjamin_Toby_CV.pdf' download={true}>See my resume</a> <a href='/documents/Benjamin_Toby_CV.pdf' download={ true }>See my resume</a>
<a href='https://www.linkedin.com/in/benjamin-toby/' target="_blank">Linkedin</a> <a href='https://www.linkedin.com/in/benjamin-toby/' target="_blank">Linkedin</a>
</div> </div>
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
</GeneralLayout> </GeneralLayout>
) )
} }

View File

@ -3,10 +3,15 @@ import Head from 'next/head'
import TextShuffler from '../components/actions/TextShuffler' import TextShuffler from '../components/actions/TextShuffler'
import GeneralLayout from '../layouts/general_layout/GeneralLayout' import GeneralLayout from '../layouts/general_layout/GeneralLayout'
import PortfolioEntry from '../components/PortfolioEntry' import PortfolioEntry from '../components/PortfolioEntry'
import threeJsAnimations from '../functions/frontend/threeJsAnimations'
const about = () => { const about = () => {
const portfolioEntries = require("../components/portfolioEntries.json"); const portfolioEntries = require("../components/portfolioEntries.json");
React.useEffect(() => {
threeJsAnimations()
}, [])
return ( return (
<GeneralLayout> <GeneralLayout>
<Head> <Head>
@ -20,8 +25,8 @@ const about = () => {
<div className='portfolio-entries-block'> <div className='portfolio-entries-block'>
{ portfolioEntries.map(entry => <PortfolioEntry key={ entry.title } title={ entry.title } description={ entry.description } url={ entry.url } image={ entry.image } />) } { portfolioEntries.map(entry => <PortfolioEntry key={ entry.title } title={ entry.title } description={ entry.description } url={ entry.url } image={ entry.image } />) }
</div> </div>
<div className='fixed top-0 left-0 -z-10' id='homepage-animation-wrapper'></div>
</GeneralLayout> </GeneralLayout>
) )
} }

View File

@ -1,11 +1,14 @@
@import url("https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap");
html { html {
width: 100%; width: 100%;
/* overflow-x: hidden; */ /* overflow-x: hidden; */
scroll-behavior: smooth; scroll-behavior: smooth;
font-family: Helvetica; font-family: "Source Code Pro", Helvetica;
font-size: 16px; font-size: 16px;
line-height: 1.5; line-height: 1.5;
color: #222; color: #222;
letter-spacing: -0.8px;
} }
* { * {
@ -21,6 +24,7 @@ html {
--sec-color-4: #adb2d3; --sec-color-4: #adb2d3;
--sec-color-5: #c2a878; --sec-color-5: #c2a878;
--light-color-1: #ddd; --light-color-1: #ddd;
--test-color: rgb(224, 64, 64);
--transparent-white: rgba(255, 255, 255, 0.2); --transparent-white: rgba(255, 255, 255, 0.2);
} }
@ -213,7 +217,7 @@ nav a:hover {
.hero-ctas-section { .hero-ctas-section {
display: flex; display: flex;
align-items: center; align-items: center;
margin-top: 20px; margin-top: 40px;
gap: 20px; gap: 20px;
} }
@ -305,6 +309,12 @@ textarea {
border: 2px solid #d42222; border: 2px solid #d42222;
} }
#homepage-animation-wrapper {
width: 150%;
height: 100%;
background-color: var(--dark-color);
}
/* ############################################################################################### /* ###############################################################################################
################################################################################################## ##################################################################################################
################################################################################################## ##################################################################################################

126
styles/tw_main.css Normal file
View File

@ -0,0 +1,126 @@
*, ::before, ::after {
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-pan-x: ;
--tw-pan-y: ;
--tw-pinch-zoom: ;
--tw-scroll-snap-strictness: proximity;
--tw-ordinal: ;
--tw-slashed-zero: ;
--tw-numeric-figure: ;
--tw-numeric-spacing: ;
--tw-numeric-fraction: ;
--tw-ring-inset: ;
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: ;
--tw-brightness: ;
--tw-contrast: ;
--tw-grayscale: ;
--tw-hue-rotate: ;
--tw-invert: ;
--tw-saturate: ;
--tw-sepia: ;
--tw-drop-shadow: ;
--tw-backdrop-blur: ;
--tw-backdrop-brightness: ;
--tw-backdrop-contrast: ;
--tw-backdrop-grayscale: ;
--tw-backdrop-hue-rotate: ;
--tw-backdrop-invert: ;
--tw-backdrop-opacity: ;
--tw-backdrop-saturate: ;
--tw-backdrop-sepia:
}
.fixed {
position: fixed
}
.absolute {
position: absolute
}
.top-4 {
top: 1rem
}
.left-4 {
left: 1rem
}
.right-4 {
right: 1rem
}
.top-0 {
top: 0px
}
.right-0 {
right: 0px
}
.left-0 {
left: 0px
}
.-z-10 {
z-index: -10
}
.block {
display: block
}
.h-10 {
height: 2.5rem
}
.h-28 {
height: 7rem
}
.h-96 {
height: 24rem
}
.h-full {
height: 100%
}
.w-10 {
width: 2.5rem
}
.w-28 {
width: 7rem
}
.w-96 {
width: 24rem
}
.w-full {
width: 100%
}
.bg-slate-600 {
--tw-bg-opacity: 1;
background-color: rgb(71 85 105 / var(--tw-bg-opacity))
}
.bg-red-600 {
--tw-bg-opacity: 1;
background-color: rgb(220 38 38 / var(--tw-bg-opacity))
}

31
tailwind.config.js Normal file
View File

@ -0,0 +1,31 @@
module.exports = {
content: ["./components/**/*.{html,js,jsx}", "./pages/**/*.jsx"],
theme: {
screens: {
xs: "350px",
sm: "450px",
md: "600px",
sl: "800px",
lg: "976px",
xl: "1200px",
},
// colors: {},
fontFamily: {
sans: ["Graphik", "sans-serif"],
serif: ["Merriweather", "serif"],
},
// extend: {
// spacing: {
// 128: "32rem",
// 144: "36rem",
// },
// borderRadius: {
// "4xl": "2rem",
// },
// },
},
plugins: [],
corePlugins: {
preflight: false,
},
};

3
tailwind/tw_main.css Normal file
View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;