Skip to content

Commit

Permalink
fix: multiple issues with the follower
Browse files Browse the repository at this point in the history
  • Loading branch information
adnan-td committed Nov 23, 2023
1 parent 0113a4a commit 4410585
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 73 deletions.
4 changes: 1 addition & 3 deletions src/component/follower.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import useMouseStore from '../store/index.js';
import { FollowerInitialiserComponent } from './follower_init.js';

export function Follower() {
const { options } = useMouseStore((state) => ({ options: state.curSettings }));
return <FollowerInitialiserComponent options={options} />;
return <FollowerInitialiserComponent />;
}
70 changes: 42 additions & 28 deletions src/component/follower_div.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { MousePosition, MouseSettings } from '../types/index.js';
import { motion } from 'framer-motion';
import { AnimatePresence, motion } from 'framer-motion';

export function FollowerDiv({ pos, options }: { pos: MousePosition; options: MouseSettings }) {
const calculatePosition = (): MousePosition => {
if (options.customLocation != undefined) {
if (options.customLocation != null) {
return { x: options.customLocation.x, y: options.customLocation.y };
} else if (options.customPosition != undefined) {
} else if (options.customPosition != null) {
const rect = options.customPosition.current.getBoundingClientRect();
const x = rect.left + rect.width / 2 - options.radius;
const y = rect.top + rect.height / 2 - options.radius;
const radius = options.radius ? options.radius : 12 / 2;
const x = rect.left + rect.width / 2 - radius;
const y = rect.top + rect.height / 2 - radius;
return { x, y };
} else {
return { x: pos.x, y: pos.y };
Expand All @@ -20,22 +21,20 @@ export function FollowerDiv({ pos, options }: { pos: MousePosition; options: Mou
x: pos.x,
y: pos.y,
scale: 0,
backgroundColor: options.backgroundColor || 'black',
zIndex: options.zIndex || -5,
mixBlendMode: options.mixBlendMode || 'initial',
}}
animate={{
x: calculatePosition().x,
y: calculatePosition().y,
scale: options.scale || 1,
scale: options.scale != null ? options.scale : 1,
rotate: options.rotate || 0,
}}
exit={{
x: pos.x,
y: pos.y,
scale: 0,
}}
style={{
backgroundColor: options.backgroundColor || 'black',
mixBlendMode: options.mixBlendMode || 'initial',
zIndex: options.zIndex || -5,
mixBlendMode: options.mixBlendMode || 'initial',
}}
style={{
position: 'fixed',
inset: 0,
pointerEvents: 'none',
Expand Down Expand Up @@ -72,21 +71,36 @@ export function FollowerDiv({ pos, options }: { pos: MousePosition; options: Mou
}}
>
{options.text && !options.backgroundElement ? (
<p
style={{
width: '85%',
textAlign: 'center',
lineHeight: options.textLineHeight,
letterSpacing: options.textLetterSpacing,
fontFamily: options.textFontFamily,
fontSize: options.textFontSize ? options.textFontSize : '12px',
color: options.textColor ? options.textColor : 'white',
}}
>
{options.text}
</p>
<AnimatePresence mode="wait">
<motion.p
animate={{ opacity: 1 }}
exit={{ opacity: 0.3 }}
transition={{ type: 'tween', duration: options.followSpeed ? 0.3 / options.followSpeed : 0.3, ease: 'circOut' }}
style={{
width: '85%',
textAlign: 'center',
lineHeight: options.textLineHeight,
letterSpacing: options.textLetterSpacing,
fontFamily: options.textFontFamily,
fontSize: options.textFontSize ? options.textFontSize : '12px',
color: options.textColor ? options.textColor : 'white',
}}
>
{options.text}
</motion.p>
</AnimatePresence>
) : null}
{options.backgroundElement ? options.backgroundElement : null}
<AnimatePresence mode="wait">
{options.backgroundElement ? (
<motion.div
animate={{ opacity: 1 }}
exit={{ opacity: 0.3 }}
transition={{ type: 'tween', duration: options.followSpeed ? 0.3 / options.followSpeed : 0.3, ease: 'circOut' }}
>
{options.backgroundElement}
</motion.div>
) : null}
</AnimatePresence>
</div>
</div>
</motion.div>
Expand Down
44 changes: 32 additions & 12 deletions src/component/follower_init.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { useEffect, useState } from 'react';
import { AnimatePresence } from 'framer-motion';
import type { MousePosition, MouseSettings } from '../types/index.js';
import { MouseSettings, type MousePosition } from '../types/index.js';
import { FollowerDiv } from './follower_div.js';
import useMouseStore from '../store/index.js';
import { AnimatePresence } from 'framer-motion';

const defaultRadius = 12 / 2;

export function FollowerInitialiserComponent({ options }: { options: MouseSettings }) {
export function FollowerInitialiserComponent() {
const [isHovering, setIsHovering] = useState<boolean>(false);
const [pos, setPos] = useState<MousePosition>({
x: 0,
y: 0,
});

const options = useMouseStore((store) => store.curSettings);
// console.log(options);

useEffect(() => {
const handleMouseLeave = () => {
Expand All @@ -29,12 +31,30 @@ export function FollowerInitialiserComponent({ options }: { options: MouseSettin
};
}, []);

return (
<ManagePosition options={!isHovering ? { ...options, scale: 0, customLocation: null, customPosition: null } : options} />
);
}

function ManagePosition({ options }: { options: MouseSettings }) {
const [pos, setPos] = useState<MousePosition>({
x: 0,
y: 0,
});

useEffect(() => {
const mouseMove = (event: any) => {
setPos({
x: event.clientX - options.radius,
y: event.clientY - options.radius,
});
if (options.radius != null) {
setPos({
x: event.clientX - options.radius,
y: event.clientY - options.radius,
});
} else {
setPos({
x: event.clientX - defaultRadius,
y: event.clientY - defaultRadius,
});
}
};
window.addEventListener('mousemove', mouseMove);
return () => {
Expand All @@ -44,7 +64,7 @@ export function FollowerInitialiserComponent({ options }: { options: MouseSettin

return (
<AnimatePresence mode="wait">
{isHovering && options.visible !== false ? <FollowerDiv options={options} pos={pos} /> : null}
{options.visible !== false ? <FollowerDiv options={options} pos={pos} /> : null}
</AnimatePresence>
);
}
70 changes: 41 additions & 29 deletions src/store/index.ts
Original file line number Diff line number Diff line change
@@ -1,42 +1,54 @@
import { create } from 'zustand';
// import { create } from 'zustand';
import { create, StateCreator, StoreApi, SetState, GetState } from 'zustand';
import { MouseSettings } from '../types/index.js';

const defaultSettings: MouseSettings = {
radius: 12 / 2,
};

interface useMouseStoreInterface {
curSettings: MouseSettings;
layers: [MouseSettings];
layers: MouseSettings[];

pushLayer: (newLayer: MouseSettings) => void;
popLayer: () => void;
clearLayers: () => void;
}

const useMouseStore = create<useMouseStoreInterface>((set) => ({
curSettings: defaultSettings,
layers: [defaultSettings],
const log =
(config: StateCreator<useMouseStoreInterface>) =>
(set: SetState<useMouseStoreInterface>, get: GetState<useMouseStoreInterface>, api: StoreApi<useMouseStoreInterface>) =>
config(
(args) => {
console.log(' applying', args);
set(args);
console.log(' new state', get());
},
get,
api,
);

const useMouseStore = create<useMouseStoreInterface>(
log((set) => ({
curSettings: {},
layers: [],

pushLayer: (newLayer: MouseSettings) =>
set((state) => {
const newCur = { ...state.curSettings, ...newLayer };
state.layers.push(newCur);
return { layers: state.layers, curSettings: newCur };
}),
popLayer: () =>
set((state) => {
if (state.layers.length > 1) {
state.layers.pop();
return { layers: state.layers, curSettings: state.layers.at(state.layers.length - 1) };
} else {
return { layers: [defaultSettings], curSettings: defaultSettings };
}
}),
clearLayers: () =>
set((state) => {
return { layers: [defaultSettings], curSettings: defaultSettings };
}),
}));
pushLayer: (newLayer: MouseSettings) =>
set((state) => {
const newCur = { ...state.curSettings, ...newLayer };
state.layers.push(newCur);
return { layers: state.layers, curSettings: newCur };
}),
popLayer: () =>
set((state) => {
if (state.layers.length > 1) {
state.layers.pop();
return { layers: state.layers, curSettings: state.layers.at(state.layers.length - 1) };
} else {
return { layers: [], curSettings: {} };
}
}),
clearLayers: () =>
set((state) => {
return { layers: [], curSettings: {} };
}),
})),
);

export default useMouseStore;
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"target": "es6",
"useDefineForClassFields": true,
"lib": ["es5", "es2015", "es2016", "dom", "esnext", "es2020"],
"module": "ESNext",
"module": "NodeNext",
"moduleResolution": "nodenext",
"noImplicitAny": true,
"skipLibCheck": true,
Expand Down

0 comments on commit 4410585

Please sign in to comment.