diff --git a/src/App.jsx b/src/App.jsx index bbad694..93c5933 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,4 +1,3 @@ - import React, { useState, useEffect } from "react"; import { BrowserRouter, Routes, Route, useLocation } from "react-router-dom"; import { AnimatePresence, LayoutGroup } from "framer-motion"; @@ -25,7 +24,6 @@ import DepartmentDetail7 from "./Components/Sections/DepartmentDetail7/Departmen import DepartmentDetail8 from "./Components/Sections/DepartmentDetail8/DepartmentDetail8"; import DepartmentDetail9 from "./Components/Sections/DepartmentDetail9/DepartmentDetail9"; - const MainPage = ({ theme }) => { return (
@@ -49,8 +47,8 @@ function RouterView({ theme, toggleTheme }) { - @@ -58,19 +56,18 @@ function RouterView({ theme, toggleTheme }) {
- } + } /> } /> } /> - } /> - } /> - } /> - } /> - } /> - - } /> - } /> + } /> + } /> + } /> + } /> + } /> + } /> + } /> @@ -82,19 +79,21 @@ function Layout({ theme, toggleTheme }) { const excludedExactPaths = [ "/department-detail2", - "/department-detail3" , - "/department-detail4" , - "/department-detail5" , - "/department-detail6" , -"/department-detail7", -"/department-detail8", -"/department-detail9" + "/department-detail3", + "/department-detail4", + "/department-detail5", + "/department-detail6", + "/department-detail7", + "/department-detail8", + "/department-detail9", ]; const excludedPrefixes = ["/departments/"]; const isExcludedExact = excludedExactPaths.includes(location.pathname); - const isExcludedPrefix = excludedPrefixes.some((p) => location.pathname.startsWith(p)); + const isExcludedPrefix = excludedPrefixes.some((p) => + location.pathname.startsWith(p), + ); const hideNavbar = isExcludedExact || isExcludedPrefix; @@ -106,7 +105,7 @@ function Layout({ theme, toggleTheme }) {
- + {location.pathname === "/" &&
}
@@ -114,13 +113,16 @@ function Layout({ theme, toggleTheme }) { } const App = () => { - const [theme, setTheme] = useState("light"); + const [theme, setTheme] = useState("dark"); useEffect(() => { console.log("Current theme:", theme); - console.log("HTML has dark class:", document.documentElement.classList.contains('dark')); - - const canvas = document.querySelector('.background-canvas'); + console.log( + "HTML has dark class:", + document.documentElement.classList.contains("dark"), + ); + + const canvas = document.querySelector(".background-canvas"); if (canvas) { console.log("Canvas found:", canvas); console.log("Canvas dimensions:", canvas.width, "x", canvas.height); @@ -131,35 +133,37 @@ const App = () => { useEffect(() => { const savedTheme = localStorage.getItem("theme"); - const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches; - - if (savedTheme === "dark" || (!savedTheme && prefersDark)) { + const prefersDark = window.matchMedia( + "(prefers-color-scheme: dark)", + ).matches; + + if (savedTheme === "light") { + setTheme("light"); + document.documentElement.classList.remove("dark"); + } else { setTheme("dark"); document.documentElement.classList.add("dark"); - } else { - document.documentElement.classList.remove("dark"); - setTheme("light"); } }, []); const toggleTheme = () => { const newTheme = theme === "light" ? "dark" : "light"; setTheme(newTheme); - + if (newTheme === "dark") { document.documentElement.classList.add("dark"); } else { document.documentElement.classList.remove("dark"); } - + localStorage.setItem("theme", newTheme); }; return ( - - - + + + ); }; -export default App; \ No newline at end of file +export default App; diff --git a/src/Components/BackgroundCanvas/BackgroundCanvas.css b/src/Components/BackgroundCanvas/BackgroundCanvas.css index b69fc4e..7f54965 100644 --- a/src/Components/BackgroundCanvas/BackgroundCanvas.css +++ b/src/Components/BackgroundCanvas/BackgroundCanvas.css @@ -1,121 +1,125 @@ html { - overflow-x: hidden !important; - height: 100% !important; + overflow-x: hidden !important; + height: 100% !important; } body { - margin: 0 !important; - padding: 0 !important; - width: 100% !important; - min-height: 100% !important; - position: relative !important; - overflow-x: hidden !important; - overflow-y: auto !important; + margin: 0 !important; + padding: 0 !important; + width: 100% !important; + min-height: 100% !important; + position: relative !important; + overflow-x: hidden !important; + overflow-y: auto !important; } .background-canvas { - position: fixed !important; - top: 0 !important; - left: 0 !important; - width: 100vw !important; - height: 100vh !important; - z-index: -1 !important; - pointer-events: none !important; - overflow: hidden !important; + position: fixed !important; + top: 0 !important; + left: 0 !important; + width: 100vw !important; + height: 100vh !important; /* Fallback */ + height: 100dvh !important; /* Dynamic Viewport Height for mobile */ + z-index: -1 !important; + pointer-events: none !important; + overflow: hidden !important; + background-color: var( + --bg-color + ); /* Ensure background color is consistent even if canvas lags */ } ::-webkit-scrollbar { - width: 0px !important; - height: 0px !important; - background: transparent !important; + width: 0px !important; + height: 0px !important; + background: transparent !important; } ::-webkit-scrollbar-track { - background: transparent !important; + background: transparent !important; } ::-webkit-scrollbar-thumb { - background: transparent !important; - border-radius: 0px !important; + background: transparent !important; + border-radius: 0px !important; } ::-webkit-scrollbar-thumb:hover { - background: transparent !important; + background: transparent !important; } * { - scrollbar-width: none !important; - scrollbar-color: transparent transparent !important; + scrollbar-width: none !important; + scrollbar-color: transparent transparent !important; } * { - -ms-overflow-style: -ms-autohiding-scrollbar !important; + -ms-overflow-style: -ms-autohiding-scrollbar !important; } * { - box-sizing: border-box; - margin: 0; - padding: 0; + box-sizing: border-box; + margin: 0; + padding: 0; } main { - position: relative !important; - z-index: 10 !important; - min-height: 100vh !important; - width: 100% !important; - /* padding: 20px !important; */ + position: relative !important; + z-index: 10 !important; + min-height: 100vh !important; + width: 100% !important; + /* padding: 20px !important; */ } nav.fixed { - z-index: 50 !important; - background: transparent !important; + z-index: 50 !important; + background: transparent !important; } @media (max-width: 768px) { - .background-canvas { - opacity: 0.8 !important; - } - body { - -webkit-overflow-scrolling: touch !important; - overscroll-behavior-y: contain !important; - } - * { - -webkit-tap-highlight-color: transparent !important; - } + .background-canvas { + opacity: 0.8 !important; + } + body { + -webkit-overflow-scrolling: touch !important; + overscroll-behavior-y: contain !important; + } + * { + -webkit-tap-highlight-color: transparent !important; + } } .content-container { - position: relative !important; - z-index: 10 !important; - height: 100% !important; - overflow-y: auto !important; - overflow-x: hidden !important; - -webkit-overflow-scrolling: touch !important; + position: relative !important; + z-index: 10 !important; + height: 100% !important; + overflow-y: auto !important; + overflow-x: hidden !important; + -webkit-overflow-scrolling: touch !important; } .scroll-container::-webkit-scrollbar { - opacity: 0; - transition: opacity 0.3s ease; + opacity: 0; + transition: opacity 0.3s ease; } .scroll-container:hover::-webkit-scrollbar { - opacity: 1; + opacity: 1; } @supports (-webkit-touch-callout: none) { - body { - height: -webkit-fill-available !important; - } - .background-canvas { - height: -webkit-fill-available !important; - } + body { + height: -webkit-fill-available !important; + } + .background-canvas { + height: -webkit-fill-available !important; + } } .fade-on-scroll { - opacity: 1; - transition: opacity 0.3s ease; + opacity: 1; + transition: opacity 0.3s ease; } .fade-on-scroll.hidden { - opacity: 0; -} \ No newline at end of file + opacity: 0; +} diff --git a/src/Components/BackgroundCanvas/BackgroundCanvas.jsx b/src/Components/BackgroundCanvas/BackgroundCanvas.jsx index c47e6c2..ac667d1 100644 --- a/src/Components/BackgroundCanvas/BackgroundCanvas.jsx +++ b/src/Components/BackgroundCanvas/BackgroundCanvas.jsx @@ -1,14 +1,14 @@ -import React, { useRef, useEffect, useState } from 'react'; -import './BackgroundCanvas.css'; +import React, { useRef, useEffect, useState } from "react"; +import "./BackgroundCanvas.css"; -const BackgroundCanvas = ({ theme = 'light' }) => { +const BackgroundCanvas = ({ theme = "light" }) => { const canvasRef = useRef(null); const animationRef = useRef(null); const jointsRef = useRef([]); const cameraRef = useRef(null); const keysRef = useRef(new Array(127).fill(0)); const worldRef = useRef({ width: 0, height: 0 }); - const themeRef = useRef(theme); + const themeRef = useRef(theme); class Camera { constructor(position, zoom) { @@ -23,10 +23,14 @@ const BackgroundCanvas = ({ theme = 'light' }) => { constructor(position, vector) { this.position = position; this.vector = vector; - this.speed = 0.5; - this.w = 2; - this.h = 2; + this.speed = Math.random() * 1.5 + 0.5; this.bone_length = 150; + const shapes = ["circle", "triangle", "square", "pentagon"]; + this.shape = shapes[Math.floor(Math.random() * shapes.length)]; + this.size = Math.random() * 4 + 3; + this.angle = 0; + this.angularSpeed = (Math.random() - 0.5) * 0.1; + this.pulse = Math.random() * Math.PI * 2; } } @@ -41,7 +45,7 @@ const BackgroundCanvas = ({ theme = 'light' }) => { { x: Math.random() * 2 - 1, y: Math.random() * 2 - 1, - } + }, ); }); return arr; @@ -52,6 +56,9 @@ const BackgroundCanvas = ({ theme = 'light' }) => { joint.position.x += joint.vector.x * joint.speed; joint.position.y += joint.vector.y * joint.speed; + joint.angle += joint.angularSpeed; + joint.pulse += 0.05; + if (joint.position.x < 0) joint.position.x = world.width; if (joint.position.x > world.width) joint.position.x = 0; if (joint.position.y < 0) joint.position.y = world.height; @@ -61,62 +68,94 @@ const BackgroundCanvas = ({ theme = 'light' }) => { const drawJoints = (ctx, joints, camera, view, theme) => { const len = joints.length; - + let lineColor, pointColor, backgroundColor; - if (theme === 'dark') { - backgroundColor = '#446a85'; - lineColor = '#FFFFFF'; - pointColor = '#F5EEE6'; + if (theme === "dark") { + backgroundColor = "#313131"; + lineColor = "#F5EEE6"; + pointColor = "#e06923"; } else { - backgroundColor = '#d3dde3'; - lineColor = '#131313'; - pointColor = '#041c40'; + backgroundColor = "#f1f1f1ff"; + lineColor = "rgba(49, 49, 49, 0.3)"; // More subtle lines + pointColor = "#041c40"; } - + ctx.fillStyle = backgroundColor; ctx.fillRect(0, 0, view.width, view.height); - + for (let i = 0; i < len; i++) { for (let j = i + 1; j < len; j += 3) { const length = Math.hypot( joints[j].position.x - joints[i].position.x, - joints[j].position.y - joints[i].position.y + joints[j].position.y - joints[i].position.y, ); - + if (length <= joints[i].bone_length) { ctx.beginPath(); ctx.strokeStyle = lineColor; ctx.lineWidth = camera.zoom * (30 / length); ctx.moveTo( - view.width / 2 + (joints[i].position.x - camera.position.x) * camera.zoom, - view.height / 2 + (joints[i].position.y - camera.position.y) * camera.zoom + view.width / 2 + + (joints[i].position.x - camera.position.x) * camera.zoom, + view.height / 2 + + (joints[i].position.y - camera.position.y) * camera.zoom, ); ctx.lineTo( - view.width / 2 + (joints[j].position.x - camera.position.x) * camera.zoom, - view.height / 2 + (joints[j].position.y - camera.position.y) * camera.zoom + view.width / 2 + + (joints[j].position.x - camera.position.x) * camera.zoom, + view.height / 2 + + (joints[j].position.y - camera.position.y) * camera.zoom, ); ctx.stroke(); ctx.closePath(); } } - - ctx.fillStyle = pointColor; - ctx.fillRect( - view.width / 2 + ((joints[i].position.x - camera.position.x) - joints[i].w / 2) * camera.zoom, - view.height / 2 + ((joints[i].position.y - camera.position.y) - joints[i].w / 2) * camera.zoom, - joints[i].w * camera.zoom, - joints[i].h * camera.zoom + + const currentSize = + (joints[i].size + Math.sin(joints[i].pulse) * 1.5) * camera.zoom; + + ctx.save(); + ctx.translate( + view.width / 2 + + (joints[i].position.x - camera.position.x) * camera.zoom, + view.height / 2 + + (joints[i].position.y - camera.position.y) * camera.zoom, ); + ctx.rotate(joints[i].angle); + + ctx.fillStyle = pointColor; + ctx.beginPath(); + + if (joints[i].shape === "circle") { + ctx.arc(0, 0, currentSize, 0, Math.PI * 2); + } else if (joints[i].shape === "triangle") { + ctx.moveTo(0, -currentSize); + ctx.lineTo(currentSize, currentSize); + ctx.lineTo(-currentSize, currentSize); + } else if (joints[i].shape === "square") { + ctx.rect(-currentSize / 2, -currentSize / 2, currentSize, currentSize); + } else if (joints[i].shape === "pentagon") { + for (let k = 0; k < 5; k++) { + ctx.lineTo( + currentSize * Math.cos((k * 2 * Math.PI) / 5 - Math.PI / 2), + currentSize * Math.sin((k * 2 * Math.PI) / 5 - Math.PI / 2), + ); + } + } + + ctx.fill(); + ctx.closePath(); + ctx.restore(); } }; const moveCamera = (camera, keys) => { - if (keys[37]) camera.acceleration.x -= camera.speed; - if (keys[38]) camera.acceleration.y -= camera.speed; - if (keys[39]) camera.acceleration.x += camera.speed; - if (keys[40]) camera.acceleration.y += camera.speed; + if (keys[37]) camera.acceleration.x -= camera.speed; + if (keys[38]) camera.acceleration.y -= camera.speed; + if (keys[39]) camera.acceleration.x += camera.speed; + if (keys[40]) camera.acceleration.y += camera.speed; if (keys[188]) camera.acceleration.z += 0.003; - if (keys[190]) camera.acceleration.z -= 0.003; + if (keys[190]) camera.acceleration.z -= 0.003; camera.position.x += camera.acceleration.x; camera.position.y += camera.acceleration.y; @@ -127,49 +166,53 @@ const BackgroundCanvas = ({ theme = 'light' }) => { camera.acceleration.z *= 0.9; }; -const initCanvas = () => { - const canvas = canvasRef.current; - if (!canvas) return; + const initCanvas = () => { + const canvas = canvasRef.current; + if (!canvas) return; - const ctx = canvas.getContext('2d'); - const view = { - width: window.innerWidth, - height: window.innerHeight, + const ctx = canvas.getContext("2d"); + const view = { + width: window.innerWidth, + height: window.innerHeight, + }; + + canvas.width = view.width; + canvas.height = view.height; + + worldRef.current = { + width: view.width * 2, + height: view.height * 2, + }; + + cameraRef.current = new Camera( + { + x: worldRef.current.width / 2, + y: worldRef.current.height / 2, + }, + 1, + ); + + const isMobile = window.innerWidth < 768; + const numberOfJoints = isMobile ? 150 : 600; + jointsRef.current = generateJoints( + numberOfJoints, + worldRef.current.width, + worldRef.current.height, + ); + + if (isMobile) { + jointsRef.current.forEach((joint) => { + joint.bone_length = 120; + joint.speed = 0.4; + }); + } }; - canvas.width = view.width; - canvas.height = view.height; - - worldRef.current = { - width: view.width * 2, - height: view.height * 2, - }; - - cameraRef.current = new Camera( - { - x: worldRef.current.width / 2, - y: worldRef.current.height / 2, - }, - 1 - ); - - const isMobile = window.innerWidth < 768; - const numberOfJoints = isMobile ? 80 : 300; - jointsRef.current = generateJoints(numberOfJoints, worldRef.current.width, worldRef.current.height); - - if (isMobile) { - jointsRef.current.forEach(joint => { - joint.bone_length = 120; - joint.speed = 0.4; - }); - } -}; - const animate = () => { const canvas = canvasRef.current; if (!canvas) return; - const ctx = canvas.getContext('2d'); + const ctx = canvas.getContext("2d"); const view = { width: canvas.width, height: canvas.height, @@ -177,8 +220,14 @@ const initCanvas = () => { moveCamera(cameraRef.current, keysRef.current); moveJoints(jointsRef.current, worldRef.current); - - drawJoints(ctx, jointsRef.current, cameraRef.current, view, themeRef.current); + + drawJoints( + ctx, + jointsRef.current, + cameraRef.current, + view, + themeRef.current, + ); animationRef.current = requestAnimationFrame(animate); }; @@ -196,12 +245,12 @@ const initCanvas = () => { keysRef.current[e.keyCode] = 0; }; - window.addEventListener('keydown', handleKeyDown); - window.addEventListener('keyup', handleKeyUp); + window.addEventListener("keydown", handleKeyDown); + window.addEventListener("keyup", handleKeyUp); return () => { - window.removeEventListener('keydown', handleKeyDown); - window.removeEventListener('keyup', handleKeyUp); + window.removeEventListener("keydown", handleKeyDown); + window.removeEventListener("keyup", handleKeyUp); }; }, []); @@ -219,8 +268,8 @@ const initCanvas = () => { }; }; - window.addEventListener('resize', handleResize); - return () => window.removeEventListener('resize', handleResize); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); }, []); useEffect(() => { @@ -232,15 +281,11 @@ const initCanvas = () => { cancelAnimationFrame(animationRef.current); } }; - }, []); + }, []); return ( -