Skip to content

Commit

Permalink
improve code stability and cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
sayjeyhi committed Oct 17, 2023
1 parent 72def14 commit 0118706
Show file tree
Hide file tree
Showing 10 changed files with 1,943 additions and 507 deletions.
34 changes: 34 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module.exports = {
"env": {
"browser": true,
"es2021": true
},
"extends": [
"plugin:react/recommended"
],
"overrides": [
{
"env": {
"node": true
},
"files": [
".eslintrc.{js,cjs}"
],
"parserOptions": {
"sourceType": "script"
}
}
],
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"react"
],
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
"react/no-unknown-property": "off"
}
}
10 changes: 10 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"jsxBracketSameLine": true,
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"arrowParens": "avoid"
}
11 changes: 10 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"gsap": "^3.12.0",
"jotai": "^2.1.1",
"leva": "^0.9.34",
"lodash-es": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"three": "0.146.0"
Expand All @@ -25,8 +26,16 @@
"@types/react-dom": "^18.0.10",
"@vitejs/plugin-react": "^3.1.0",
"autoprefixer": "^10.4.14",
"eslint": "^8.0.1",
"eslint-plugin-import": "^2.25.2",
"eslint-plugin-n": "^15.0.0 || ^16.0.0 ",
"eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"postcss": "^8.4.24",
"prettier": "3.0.3",
"tailwindcss": "^3.3.2",
"vite": "^4.1.0"
"vite": "^4.1.5"
}
}
48 changes: 21 additions & 27 deletions src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,31 @@
import { Scroll, ScrollControls } from "@react-three/drei";
import { Canvas } from "@react-three/fiber";
import { MotionConfig } from "framer-motion";
import { Leva } from "leva";
import { useEffect, useState } from "react";
import { Cursor } from "./components/Cursor";
import { Experience } from "./components/Experience";
import { Interface } from "./components/Interface";
import { Menu } from "./components/Menu";
import { ScrollManager } from "./components/ScrollManager";
import { framerMotionConfig } from "./config";
import { Scroll, ScrollControls } from '@react-three/drei'
import { Canvas } from '@react-three/fiber'
import { MotionConfig } from 'framer-motion'
import { Leva } from 'leva'
import { useEffect, useState } from 'react'
import { Cursor, CursorContextProvider } from './components/Cursor'
import { Experience } from './components/Experience'
import { Interface } from './components/Interface'
import { Menu } from './components/Menu'
import { ScrollManager } from './components/ScrollManager'
import { framerMotionConfig } from './config'

function App() {
const [section, setSection] = useState(0);
const [menuOpened, setMenuOpened] = useState(false);
const [section, setSection] = useState(0)
const [menuOpened, setMenuOpened] = useState(false)

useEffect(() => {
setMenuOpened(false);
}, [section]);
setMenuOpened(false)
}, [section])

return (
<>
<MotionConfig
transition={{
...framerMotionConfig,
}}
>
...framerMotionConfig
}}>
<Canvas shadows camera={{ position: [0, 3, 10], fov: 42 }}>
<color attach="background" args={["#f5efe6"]} />
<color attach="background" args={['#f5efe6']} />

<ScrollControls pages={4} damping={0.1}>
<ScrollManager section={section} onSectionChange={setSection} />
Expand All @@ -38,16 +37,11 @@ function App() {
</Scroll>
</ScrollControls>
</Canvas>
<Menu
onSectionChange={setSection}
menuOpened={menuOpened}
setMenuOpened={setMenuOpened}
/>
<Cursor />
<Menu onSectionChange={setSection} menuOpened={menuOpened} setMenuOpened={setMenuOpened} />
</MotionConfig>
<Leva hidden />
</>
);
)
}

export default App;
export default App
File renamed without changes.
36 changes: 0 additions & 36 deletions src/components/Background.jsx

This file was deleted.

167 changes: 104 additions & 63 deletions src/components/Cursor.jsx
Original file line number Diff line number Diff line change
@@ -1,75 +1,116 @@
import { useEffect, useRef, useState } from "react";
import { createContext, useContext, useState, useEffect, useCallback } from 'react'
import throttle from 'lodash-es/throttle'

const CURSOR_SPEED = 0.85;
const isTouchDevice =
'ontouchstart' in window || navigator.MaxTouchPoints > 0 || navigator.msMaxTouchPoints > 0

let mouseX = 0;
let mouseY = 0;
let outlineX = 0;
let outlineY = 0;
const CursorContext = createContext({ cursorActive: false, setCursorActive: state => state })

export const CursorContextProvider = ({ children }) => {
const [cursorActive, setCursorActive] = useState(false)

return (
<CursorContext.Provider
value={{
cursorActive,
setCursorActive
}}>
{children}
</CursorContext.Provider>
)
}
const useMousePosition = () => {
const [position, setPosition] = useState({
clientX: 0,
clientY: 0
})

useEffect(() => {
const updatePosition = throttle(event => {
const { clientX, clientY } = event

setPosition({
clientX,
clientY
})
}, 10)

document.body.addEventListener('mousemove', updatePosition, false)
document.body.addEventListener('mouseenter', updatePosition, false)

return () => {
document.body.removeEventListener('mousemove', updatePosition)
document.body.removeEventListener('mouseenter', updatePosition)
}
}, [])

return position
}

export const Cursor = () => {
const cursorOutline = useRef();
const [hoverButton, setHoverButton] = useState(false);
if (isTouchDevice) {
return null
}

const animate = () => {
let distX = mouseX - outlineX;
let distY = mouseY - outlineY;
const { clientX, clientY } = useMousePosition()
const { cursorActive: isCursorActive } = useContext(CursorContext)

outlineX = outlineX + distX * CURSOR_SPEED;
outlineY = outlineY + distY * CURSOR_SPEED;
return (
<svg
width={50}
height={50}
viewBox="0 0 50 50"
style={{
opacity: !clientX && !clientY ? 0 : 1,
zIndex: 9999,
position: 'absolute',
pointerEvents: 'none',
left: clientX,
top: clientY,
transform: `translate(-50%, -50%) scale(${isCursorActive ? 2.2 : 1})`,
stroke: isCursorActive ? 'rgb(49,79,227)' : 'transparent',
strokeWidth: isCursorActive ? 2 : 1,
fill: isCursorActive ? 'rgba(255,255,255,0.4)' : 'rgb(49,79,227)',
transition: 'transform .25s ease-in-out'
}}>
<circle cx="25" cy="25" r="8" />
</svg>
)
}

cursorOutline.current.style.left = `${outlineX}px`;
cursorOutline.current.style.top = `${outlineY}px`;
requestAnimationFrame(animate);
};
export const useCursorHandlers = (options = {}) => {
const context = useContext(CursorContext)
if (!context) {
throw new Error('useBrand must be used within a CursorContext')
}

useEffect(() => {
const mouseEventsListener = document.addEventListener(
"mousemove",
function (event) {
mouseX = event.pageX;
mouseY = event.pageY;
const { setCursorActive } = context

const onMouseEnter = useCallback(
event => {
if (options.onMouseEnter) {
options.onMouseEnter(event)
}
);
const animateEvent = requestAnimationFrame(animate);
return () => {
document.removeEventListener("mousemove", mouseEventsListener);
cancelAnimationFrame(animateEvent);
};
}, []);

useEffect(() => {
const mouseEventListener = document.addEventListener(
"mouseover",
function (e) {
if (
e.target.tagName.toLowerCase() === "button" ||
// check parent is button
e.target.parentElement.tagName.toLowerCase() === "button" ||
// check is input or textarea
e.target.tagName.toLowerCase() === "input" ||
e.target.tagName.toLowerCase() === "textarea"
) {
setHoverButton(true);
} else {
setHoverButton(false);
}
setCursorActive(true)
},
[setCursorActive]
)

const onMouseLeave = useCallback(
event => {
if (options.onMouseLeave) {
options.onMouseLeave(event)
}
);
return () => {
document.removeEventListener("mouseover", mouseEventListener);
};
}, []);

return (
<div
className={`z-50 fixed w-5 h-5 -translate-x-1/2 -translate-y-1/2 rounded-full pointer-events-none transition-all
${
hoverButton
? "bg-transparent border-4 border-gray-900 scale-150"
: "bg-indigo-500"
}`}
ref={cursorOutline}
/>
);
};
setCursorActive(false)
},
[setCursorActive]
)

if (isTouchDevice) {
return options
}

return { onMouseEnter, onMouseLeave }
}
Loading

0 comments on commit 0118706

Please sign in to comment.