Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 53 additions & 10 deletions src/content/Animations/TargetCursor/TargetCursor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ const TargetCursor = ({
spinDuration = 2,
hideDefaultCursor = true,
hoverDuration = 0.2,
parallaxOn = true
parallaxOn = true,
cursorColor = '#ffffff',
cursorColorOnTarget
}) => {
const cursorRef = useRef(null);
const cornersRef = useRef(null);
Expand Down Expand Up @@ -217,12 +219,27 @@ const TargetCursor = ({

activeTarget = target;
const corners = Array.from(cornersRef.current);
corners.forEach(corner => gsap.killTweensOf(corner));
corners.forEach(corner => gsap.killTweensOf(corner, 'x,y'));

gsap.killTweensOf(cursorRef.current, 'rotation');
spinTl.current?.pause();
gsap.set(cursorRef.current, { rotation: 0 });

if (cursorColorOnTarget) {
gsap.to(corners, {
borderColor: cursorColorOnTarget,
duration: 0.15,
ease: 'power2.out'
});
if (dotRef.current) {
gsap.to(dotRef.current, {
backgroundColor: cursorColorOnTarget,
duration: 0.15,
ease: 'power2.out'
});
}
}

const rect = target.getBoundingClientRect();
const { borderWidth, cornerSize } = constants;
const { x: offsetX, y: offsetY } = getOffset();
Expand Down Expand Up @@ -262,9 +279,24 @@ const TargetCursor = ({
gsap.set(activeStrengthRef, { current: 0, overwrite: true });
activeTarget = null;

if (cursorColorOnTarget && cornersRef.current) {
gsap.to(Array.from(cornersRef.current), {
borderColor: cursorColor,
duration: 0.15,
ease: 'power2.out'
});
if (dotRef.current) {
gsap.to(dotRef.current, {
backgroundColor: cursorColor,
duration: 0.15,
ease: 'power2.out'
});
}
}

if (cornersRef.current) {
const corners = Array.from(cornersRef.current);
gsap.killTweensOf(corners);
gsap.killTweensOf(corners, 'x,y');
const { cornerSize } = constants;
const positions = [
{ x: -cornerSize * 1.5, y: -cornerSize * 1.5 },
Expand Down Expand Up @@ -344,7 +376,18 @@ const TargetCursor = ({
targetCornerPositionsRef.current = null;
activeStrengthRef.current = 0;
};
}, [targetSelector, spinDuration, moveCursor, constants, hideDefaultCursor, isMobile, hoverDuration, parallaxOn]);
}, [
targetSelector,
spinDuration,
moveCursor,
constants,
hideDefaultCursor,
isMobile,
hoverDuration,
parallaxOn,
cursorColor,
cursorColorOnTarget
]);

useEffect(() => {
if (isMobile || !cursorRef.current || !spinTl.current) return;
Expand All @@ -362,13 +405,13 @@ const TargetCursor = ({

return (
<div ref={cursorRef} className="target-cursor-wrapper">
<div ref={dotRef} className="target-cursor-dot" />
<div className="target-cursor-corner corner-tl" />
<div className="target-cursor-corner corner-tr" />
<div className="target-cursor-corner corner-br" />
<div className="target-cursor-corner corner-bl" />
<div ref={dotRef} className="target-cursor-dot" style={{ backgroundColor: cursorColor }} />
<div className="target-cursor-corner corner-tl" style={{ borderColor: cursorColor }} />
<div className="target-cursor-corner corner-tr" style={{ borderColor: cursorColor }} />
<div className="target-cursor-corner corner-br" style={{ borderColor: cursorColor }} />
<div className="target-cursor-corner corner-bl" style={{ borderColor: cursorColor }} />
</div>
);
};

export default TargetCursor;
export default TargetCursor;
33 changes: 30 additions & 3 deletions src/demo/Animations/TargetCursorDemo.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import PropTable from '../../components/common/Preview/PropTable';
import Dependencies from '../../components/code/Dependencies';
import PreviewSlider from '../../components/common/Preview/PreviewSlider';
import PreviewSwitch from '../../components/common/Preview/PreviewSwitch';
import PreviewColorPickerCustom from '../../components/common/Preview/PreviewColorPickerCustom';

import TargetCursor from '../../content/Animations/TargetCursor/TargetCursor';
import { targetCursor } from '../../constants/code/Animations/targetCursorCode';
Expand All @@ -19,12 +20,14 @@ const DEFAULT_PROPS = {
spinDuration: 2,
hideDefaultCursor: true,
hoverDuration: 0.2,
parallaxOn: true
parallaxOn: true,
cursorColor: '#ffffff',
cursorColorOnTarget: '#B497CF'
};

const TargetCursorDemo = () => {
const { props, updateProp, resetProps, hasChanges } = useComponentProps(DEFAULT_PROPS);
const { spinDuration, hideDefaultCursor, hoverDuration, parallaxOn } = props;
const { spinDuration, hideDefaultCursor, hoverDuration, parallaxOn, cursorColor, cursorColorOnTarget } = props;

const propData = useMemo(
() => [
Expand Down Expand Up @@ -57,6 +60,18 @@ const TargetCursorDemo = () => {
type: 'boolean',
default: 'true',
description: 'Enables a subtle parallax effect on the corners when moving over a target'
},
{
name: 'cursorColor',
type: 'string',
default: "'#ffffff'",
description: 'Color of the cursor dot and corner brackets at rest'
},
{
name: 'cursorColorOnTarget',
type: 'string',
default: 'undefined',
description: 'Optional color the cursor smoothly transitions to while locked onto a target'
}
],
[]
Expand Down Expand Up @@ -172,6 +187,16 @@ const TargetCursorDemo = () => {
isChecked={parallaxOn}
onChange={val => updateProp('parallaxOn', val)}
/>
<PreviewColorPickerCustom
title="Cursor Color"
color={cursorColor}
onChange={val => updateProp('cursorColor', val)}
/>
<PreviewColorPickerCustom
title="Cursor Color On Target"
color={cursorColorOnTarget}
onChange={val => updateProp('cursorColorOnTarget', val)}
/>
</Customize>

<PropTable data={propData} />
Expand All @@ -189,9 +214,11 @@ const TargetCursorDemo = () => {
hideDefaultCursor={hideDefaultCursor}
hoverDuration={hoverDuration}
parallaxOn={parallaxOn}
cursorColor={cursorColor}
cursorColorOnTarget={cursorColorOnTarget}
/>
</>
);
};

export default TargetCursorDemo;
export default TargetCursorDemo;
74 changes: 59 additions & 15 deletions src/tailwind/Animations/TargetCursor/TargetCursor.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ const TargetCursor = ({
spinDuration = 2,
hideDefaultCursor = true,
hoverDuration = 0.2,
parallaxOn = true
parallaxOn = true,
cursorColor = '#ffffff',
cursorColorOnTarget
}) => {
const cursorRef = useRef(null);
const cornersRef = useRef(null);
Expand Down Expand Up @@ -209,11 +211,26 @@ const TargetCursor = ({

activeTarget = target;
const corners = Array.from(cornersRef.current);
corners.forEach(corner => gsap.killTweensOf(corner));
corners.forEach(corner => gsap.killTweensOf(corner, 'x,y'));
gsap.killTweensOf(cursorRef.current, 'rotation');
spinTl.current?.pause();
gsap.set(cursorRef.current, { rotation: 0 });

if (cursorColorOnTarget) {
gsap.to(corners, {
borderColor: cursorColorOnTarget,
duration: 0.15,
ease: 'power2.out'
});
if (dotRef.current) {
gsap.to(dotRef.current, {
backgroundColor: cursorColorOnTarget,
duration: 0.15,
ease: 'power2.out'
});
}
}

const rect = target.getBoundingClientRect();
const { borderWidth, cornerSize } = constants;
const { x: offsetX, y: offsetY } = getOffset();
Expand Down Expand Up @@ -247,9 +264,25 @@ const TargetCursor = ({
targetCornerPositionsRef.current = null;
gsap.set(activeStrengthRef, { current: 0, overwrite: true });
activeTarget = null;

if (cursorColorOnTarget && cornersRef.current) {
gsap.to(Array.from(cornersRef.current), {
borderColor: cursorColor,
duration: 0.15,
ease: 'power2.out'
});
if (dotRef.current) {
gsap.to(dotRef.current, {
backgroundColor: cursorColor,
duration: 0.15,
ease: 'power2.out'
});
}
}

if (cornersRef.current) {
const corners = Array.from(cornersRef.current);
gsap.killTweensOf(corners);
gsap.killTweensOf(corners, 'x,y');
const { cornerSize } = constants;
const positions = [
{ x: -cornerSize * 1.5, y: -cornerSize * 1.5 },
Expand Down Expand Up @@ -313,7 +346,18 @@ const TargetCursor = ({
targetCornerPositionsRef.current = null;
activeStrengthRef.current = 0;
};
}, [targetSelector, spinDuration, moveCursor, constants, hideDefaultCursor, isMobile, hoverDuration, parallaxOn]);
}, [
targetSelector,
spinDuration,
moveCursor,
constants,
hideDefaultCursor,
isMobile,
hoverDuration,
parallaxOn,
cursorColor,
cursorColorOnTarget
]);

useEffect(() => {
if (isMobile || !cursorRef.current || !spinTl.current) return;
Expand All @@ -337,27 +381,27 @@ const TargetCursor = ({
>
<div
ref={dotRef}
className="absolute top-1/2 left-1/2 w-1 h-1 bg-white rounded-full -translate-x-1/2 -translate-y-1/2"
style={{ willChange: 'transform' }}
className="absolute top-1/2 left-1/2 w-1 h-1 rounded-full -translate-x-1/2 -translate-y-1/2"
style={{ willChange: 'transform', backgroundColor: cursorColor }}
/>
<div
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] border-white -translate-x-[150%] -translate-y-[150%] border-r-0 border-b-0"
style={{ willChange: 'transform' }}
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] -translate-x-[150%] -translate-y-[150%] border-r-0 border-b-0"
style={{ willChange: 'transform', borderColor: cursorColor }}
/>
<div
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] border-white translate-x-1/2 -translate-y-[150%] border-l-0 border-b-0"
style={{ willChange: 'transform' }}
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] translate-x-1/2 -translate-y-[150%] border-l-0 border-b-0"
style={{ willChange: 'transform', borderColor: cursorColor }}
/>
<div
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] border-white translate-x-1/2 translate-y-1/2 border-l-0 border-t-0"
style={{ willChange: 'transform' }}
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] translate-x-1/2 translate-y-1/2 border-l-0 border-t-0"
style={{ willChange: 'transform', borderColor: cursorColor }}
/>
<div
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] border-white -translate-x-[150%] translate-y-1/2 border-r-0 border-t-0"
style={{ willChange: 'transform' }}
className="target-cursor-corner absolute top-1/2 left-1/2 w-3 h-3 border-[3px] -translate-x-[150%] translate-y-1/2 border-r-0 border-t-0"
style={{ willChange: 'transform', borderColor: cursorColor }}
/>
</div>
);
};

export default TargetCursor;
export default TargetCursor;
Loading