fix: remove distracting parallax and wobble 3D effects
Remove all parallax hover effects and wobble physics from 3D enhancement system as they were distracting and worsened the user experience. Changes: - Remove Abacus3DPhysics interface completely - Remove physics3d prop from AbacusConfig and component - Remove calculateParallaxOffset utility function - Remove mouse tracking infrastructure (containerRef, mousePos, handleMouseMove) - Update enhanced3d type to only support 'subtle' | 'realistic' (removed 'delightful') - Update all 3D utilities to remove delightful mode support - Remove all Delightful stories from Storybook - Update Interactive Playground to remove parallax controls - Change MyAbacus from delightful to realistic mode The 3D enhancement system now focuses purely on visual improvements (materials, lighting, textures) without any motion-based effects. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
37e330f26e
commit
28a2d40996
|
|
@ -235,8 +235,8 @@ export function MyAbacus() {
|
|||
animated={isOpen || isHeroMode}
|
||||
customStyles={isHeroMode ? structuralStyles : trophyStyles}
|
||||
onValueChange={setAbacusValue}
|
||||
// 3D Enhancement - delightful mode for hero and open states
|
||||
enhanced3d={isOpen || isHeroMode ? 'delightful' : undefined}
|
||||
// 3D Enhancement - realistic mode for hero and open states
|
||||
enhanced3d={isOpen || isHeroMode ? 'realistic' : undefined}
|
||||
material3d={
|
||||
isOpen || isHeroMode
|
||||
? {
|
||||
|
|
@ -247,65 +247,10 @@ export function MyAbacus() {
|
|||
}
|
||||
: undefined
|
||||
}
|
||||
physics3d={
|
||||
isOpen || isHeroMode
|
||||
? {
|
||||
hoverParallax: true,
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Title and achievement info - only visible when open */}
|
||||
{isOpen && (
|
||||
<div
|
||||
className={css({
|
||||
position: 'absolute',
|
||||
top: '100%',
|
||||
left: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
mt: { base: '16', md: '20', lg: '24' },
|
||||
textAlign: 'center',
|
||||
animation: 'fadeIn 0.5s ease-out 0.3s both',
|
||||
maxW: '600px',
|
||||
px: '8',
|
||||
})}
|
||||
>
|
||||
<h2
|
||||
className={css({
|
||||
fontSize: { base: '2xl', md: '3xl', lg: '4xl' },
|
||||
fontWeight: 'bold',
|
||||
background: 'linear-gradient(135deg, #fbbf24 0%, #f59e0b 50%, #fbbf24 100%)',
|
||||
backgroundClip: 'text',
|
||||
color: 'transparent',
|
||||
mb: '3',
|
||||
})}
|
||||
>
|
||||
My Abacus
|
||||
</h2>
|
||||
<p
|
||||
className={css({
|
||||
fontSize: { base: 'md', md: 'lg' },
|
||||
color: 'gray.300',
|
||||
mb: '4',
|
||||
fontWeight: 'medium',
|
||||
})}
|
||||
>
|
||||
Your personal abacus grows with you
|
||||
</p>
|
||||
<p
|
||||
className={css({
|
||||
fontSize: { base: 'sm', md: 'md' },
|
||||
color: 'gray.400',
|
||||
lineHeight: '1.6',
|
||||
})}
|
||||
>
|
||||
Complete tutorials, play games, and earn achievements to unlock higher place values
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Keyframes for animations */}
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ export function getLightingFilter(lighting: LightingStyle = "top-down"): string
|
|||
* Calculate Z-depth for a bead based on enhancement level and state
|
||||
*/
|
||||
export function getBeadZDepth(
|
||||
enhanced3d: boolean | "subtle" | "realistic" | "delightful",
|
||||
enhanced3d: boolean | "subtle" | "realistic",
|
||||
active: boolean
|
||||
): number {
|
||||
if (!enhanced3d || enhanced3d === true) return 0;
|
||||
|
|
@ -136,48 +136,11 @@ export function getBeadZDepth(
|
|||
return 6;
|
||||
case "realistic":
|
||||
return 10;
|
||||
case "delightful":
|
||||
return 12;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate parallax offset based on mouse position
|
||||
*/
|
||||
export function calculateParallaxOffset(
|
||||
beadX: number,
|
||||
beadY: number,
|
||||
mouseX: number,
|
||||
mouseY: number,
|
||||
containerX: number,
|
||||
containerY: number,
|
||||
intensity: number = 0.5
|
||||
): { x: number; y: number; z: number } {
|
||||
// Calculate distance from bead center to mouse
|
||||
const dx = (mouseX - containerX) - beadX;
|
||||
const dy = (mouseY - containerY) - beadY;
|
||||
const distance = Math.sqrt(dx * dx + dy * dy);
|
||||
|
||||
// Max influence radius (pixels)
|
||||
const maxRadius = 150;
|
||||
|
||||
if (distance > maxRadius) {
|
||||
return { x: 0, y: 0, z: 0 };
|
||||
}
|
||||
|
||||
// Calculate lift amount (inverse square falloff)
|
||||
const influence = Math.max(0, 1 - (distance / maxRadius));
|
||||
const lift = influence * influence * intensity;
|
||||
|
||||
return {
|
||||
x: dx * lift * 0.1,
|
||||
y: dy * lift * 0.1,
|
||||
z: lift * 8
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate wood grain texture SVG pattern
|
||||
*/
|
||||
|
|
@ -203,9 +166,8 @@ export function getWoodGrainPattern(id: string): string {
|
|||
* Get container class names for 3D enhancement level
|
||||
*/
|
||||
export function get3DContainerClasses(
|
||||
enhanced3d: boolean | "subtle" | "realistic" | "delightful" | undefined,
|
||||
lighting?: LightingStyle,
|
||||
parallaxEnabled?: boolean
|
||||
enhanced3d: boolean | "subtle" | "realistic" | undefined,
|
||||
lighting?: LightingStyle
|
||||
): string {
|
||||
const classes: string[] = ["abacus-3d-container"];
|
||||
|
||||
|
|
@ -216,8 +178,6 @@ export function get3DContainerClasses(
|
|||
classes.push("enhanced-subtle");
|
||||
} else if (enhanced3d === "realistic") {
|
||||
classes.push("enhanced-realistic");
|
||||
} else if (enhanced3d === "delightful") {
|
||||
classes.push("enhanced-delightful");
|
||||
}
|
||||
|
||||
// Add lighting class
|
||||
|
|
@ -225,11 +185,6 @@ export function get3DContainerClasses(
|
|||
classes.push(`lighting-${lighting}`);
|
||||
}
|
||||
|
||||
// Add parallax class
|
||||
if (parallaxEnabled && enhanced3d === "delightful") {
|
||||
classes.push("parallax-enabled");
|
||||
}
|
||||
|
||||
return classes.join(" ");
|
||||
}
|
||||
|
||||
|
|
@ -248,7 +203,7 @@ export function getBeadGradientId(
|
|||
/**
|
||||
* Physics config for different enhancement levels
|
||||
*/
|
||||
export function getPhysicsConfig(enhanced3d: boolean | "subtle" | "realistic" | "delightful") {
|
||||
export function getPhysicsConfig(enhanced3d: boolean | "subtle" | "realistic") {
|
||||
const base = {
|
||||
tension: 300,
|
||||
friction: 22,
|
||||
|
|
@ -260,20 +215,11 @@ export function getPhysicsConfig(enhanced3d: boolean | "subtle" | "realistic" |
|
|||
return { ...base, clamp: true };
|
||||
}
|
||||
|
||||
if (enhanced3d === "realistic") {
|
||||
return {
|
||||
tension: 320,
|
||||
friction: 24,
|
||||
mass: 0.6,
|
||||
clamp: false
|
||||
};
|
||||
}
|
||||
|
||||
// delightful
|
||||
// realistic
|
||||
return {
|
||||
tension: 280,
|
||||
friction: 20,
|
||||
mass: 0.7,
|
||||
clamp: false, // Allow overshoot for satisfying settle
|
||||
tension: 320,
|
||||
friction: 24,
|
||||
mass: 0.6,
|
||||
clamp: false
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,26 +12,20 @@ const meta: Meta<typeof AbacusReact> = {
|
|||
component: `
|
||||
# 3D Enhancement Showcase
|
||||
|
||||
Three levels of progressive 3D enhancement for the abacus to make interactions feel satisfying and real.
|
||||
Two levels of progressive 3D enhancement for the abacus to make interactions feel satisfying and real.
|
||||
|
||||
## Proposal 1: Subtle (CSS Perspective + Shadows)
|
||||
## Subtle (CSS Perspective + Shadows)
|
||||
- Light perspective tilt
|
||||
- Depth shadows on active beads
|
||||
- Smooth transitions
|
||||
- **Zero performance cost**
|
||||
|
||||
## Proposal 2: Realistic (Lighting + Materials)
|
||||
- Everything from Proposal 1 +
|
||||
## Realistic (Lighting + Materials)
|
||||
- Everything from Subtle +
|
||||
- Realistic lighting effects with material gradients
|
||||
- Glossy/Satin/Matte bead materials
|
||||
- Wood grain textures on frame
|
||||
- Enhanced physics for realistic motion
|
||||
|
||||
## Proposal 3: Delightful (Physics + Micro-interactions)
|
||||
- Everything from Proposal 2 +
|
||||
- Enhanced physics with satisfying bounce
|
||||
- Hover parallax with Z-depth lift
|
||||
- Maximum satisfaction
|
||||
`
|
||||
}
|
||||
}
|
||||
|
|
@ -64,7 +58,7 @@ export const CompareAllLevels: Story = {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<h3 style={{ marginBottom: '10px', textAlign: 'center' }}>Proposal 1: Subtle</h3>
|
||||
<h3 style={{ marginBottom: '10px', textAlign: 'center' }}>Subtle</h3>
|
||||
<AbacusReact
|
||||
value={4242}
|
||||
columns={4}
|
||||
|
|
@ -78,7 +72,7 @@ export const CompareAllLevels: Story = {
|
|||
</div>
|
||||
|
||||
<div>
|
||||
<h3 style={{ marginBottom: '10px', textAlign: 'center' }}>Proposal 2: Realistic (Satin Beads + Wood Frame)</h3>
|
||||
<h3 style={{ marginBottom: '10px', textAlign: 'center' }}>Realistic (Satin Beads + Wood Frame)</h3>
|
||||
<AbacusReact
|
||||
value={4242}
|
||||
columns={4}
|
||||
|
|
@ -96,35 +90,12 @@ export const CompareAllLevels: Story = {
|
|||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 style={{ marginBottom: '10px', textAlign: 'center' }}>Proposal 3: Delightful (Glossy + Parallax)</h3>
|
||||
<AbacusReact
|
||||
value={4242}
|
||||
columns={4}
|
||||
showNumbers
|
||||
interactive
|
||||
animated
|
||||
colorScheme="place-value"
|
||||
scaleFactor={1.2}
|
||||
enhanced3d="delightful"
|
||||
material3d={{
|
||||
heavenBeads: 'glossy',
|
||||
earthBeads: 'glossy',
|
||||
lighting: 'dramatic',
|
||||
woodGrain: true
|
||||
}}
|
||||
physics3d={{
|
||||
hoverParallax: true
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: 'Side-by-side comparison of all three enhancement levels. **Click beads** to see how they move! **Hover over the Delightful version** to see parallax effect.'
|
||||
story: 'Side-by-side comparison of both enhancement levels. **Click beads** to see how they move!'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -361,100 +332,6 @@ export const Realistic_LightingComparison: Story = {
|
|||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// PROPOSAL 3: DELIGHTFUL (Physics)
|
||||
// ============================================
|
||||
|
||||
export const Delightful_FullExperience: Story = {
|
||||
name: '3️⃣ Delightful - Full Experience',
|
||||
args: {
|
||||
value: 8642,
|
||||
columns: 4,
|
||||
showNumbers: true,
|
||||
interactive: true,
|
||||
animated: true,
|
||||
soundEnabled: true,
|
||||
colorScheme: 'rainbow',
|
||||
scaleFactor: 1.4,
|
||||
enhanced3d: 'delightful',
|
||||
material3d: {
|
||||
heavenBeads: 'glossy',
|
||||
earthBeads: 'satin',
|
||||
lighting: 'dramatic',
|
||||
woodGrain: true
|
||||
},
|
||||
physics3d: {
|
||||
hoverParallax: true
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: '🎉 **Full delightful experience!** Click beads to see enhanced physics. Hover your mouse over the abacus to see parallax lift. Sound enabled for maximum satisfaction!'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const Delightful_HoverParallax: Story = {
|
||||
name: '3️⃣ Delightful - Hover Parallax',
|
||||
args: {
|
||||
value: 1234,
|
||||
columns: 4,
|
||||
showNumbers: true,
|
||||
interactive: true,
|
||||
animated: true,
|
||||
colorScheme: 'place-value',
|
||||
scaleFactor: 1.3,
|
||||
enhanced3d: 'delightful',
|
||||
material3d: {
|
||||
heavenBeads: 'satin',
|
||||
earthBeads: 'satin',
|
||||
lighting: 'ambient'
|
||||
},
|
||||
physics3d: {
|
||||
hoverParallax: true // Enable hover parallax
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: '**Hover parallax enabled!** Move your mouse over the abacus. Beads near your cursor will lift up with Z-depth. Creates magical depth perception!'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const Delightful_Traditional: Story = {
|
||||
name: '3️⃣ Delightful - Traditional Wood',
|
||||
args: {
|
||||
value: 99999,
|
||||
columns: 5,
|
||||
showNumbers: true,
|
||||
interactive: true,
|
||||
animated: true,
|
||||
colorScheme: 'monochrome',
|
||||
scaleFactor: 1.2,
|
||||
enhanced3d: 'delightful',
|
||||
material3d: {
|
||||
heavenBeads: 'matte',
|
||||
earthBeads: 'matte',
|
||||
lighting: 'ambient',
|
||||
woodGrain: true
|
||||
},
|
||||
physics3d: {
|
||||
hoverParallax: true
|
||||
}
|
||||
},
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
story: 'Traditional aesthetic with **wood grain frame** + modern delightful physics. Best of both worlds!'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================
|
||||
// INTERACTIVE PLAYGROUND
|
||||
// ============================================
|
||||
|
|
@ -462,29 +339,27 @@ export const Delightful_Traditional: Story = {
|
|||
export const Playground: Story = {
|
||||
name: '🎮 Interactive Playground',
|
||||
render: () => {
|
||||
const [level, setLevel] = React.useState<'subtle' | 'realistic' | 'delightful'>('delightful');
|
||||
const [level, setLevel] = React.useState<'subtle' | 'realistic'>('realistic');
|
||||
const [material, setMaterial] = React.useState<'glossy' | 'satin' | 'matte'>('glossy');
|
||||
const [lighting, setLighting] = React.useState<'top-down' | 'ambient' | 'dramatic'>('dramatic');
|
||||
const [woodGrain, setWoodGrain] = React.useState(true);
|
||||
const [parallax, setParallax] = React.useState(true);
|
||||
|
||||
return (
|
||||
<div style={{ display: 'flex', flexDirection: 'column', gap: '30px', alignItems: 'center' }}>
|
||||
<div style={{
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(3, 1fr)',
|
||||
gridTemplateColumns: 'repeat(2, 1fr)',
|
||||
gap: '20px',
|
||||
padding: '20px',
|
||||
background: '#f5f5f5',
|
||||
borderRadius: '8px',
|
||||
maxWidth: '600px'
|
||||
maxWidth: '500px'
|
||||
}}>
|
||||
<div>
|
||||
<label style={{ fontWeight: 'bold', display: 'block', marginBottom: '5px' }}>Enhancement Level</label>
|
||||
<select value={level} onChange={e => setLevel(e.target.value as any)} style={{ width: '100%', padding: '5px' }}>
|
||||
<option value="subtle">Subtle</option>
|
||||
<option value="realistic">Realistic</option>
|
||||
<option value="delightful">Delightful</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
|
|
@ -512,13 +387,6 @@ export const Playground: Story = {
|
|||
<span>Wood Grain</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: '5px' }}>
|
||||
<input type="checkbox" checked={parallax} onChange={e => setParallax(e.target.checked)} />
|
||||
<span>Hover Parallax (Delightful)</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<AbacusReact
|
||||
|
|
@ -537,9 +405,6 @@ export const Playground: Story = {
|
|||
lighting: lighting,
|
||||
woodGrain: woodGrain
|
||||
}}
|
||||
physics3d={{
|
||||
hoverParallax: parallax
|
||||
}}
|
||||
/>
|
||||
|
||||
<p style={{ maxWidth: '500px', textAlign: 'center', color: '#666' }}>
|
||||
|
|
|
|||
|
|
@ -253,10 +253,6 @@ export interface Abacus3DMaterial {
|
|||
woodGrain?: boolean; // Add wood texture to frame
|
||||
}
|
||||
|
||||
export interface Abacus3DPhysics {
|
||||
hoverParallax?: boolean; // Beads lift on hover (delightful mode only)
|
||||
}
|
||||
|
||||
export interface AbacusConfig {
|
||||
// Basic configuration
|
||||
value?: number | bigint;
|
||||
|
|
@ -275,9 +271,8 @@ export interface AbacusConfig {
|
|||
soundVolume?: number;
|
||||
|
||||
// 3D Enhancement
|
||||
enhanced3d?: boolean | "subtle" | "realistic" | "delightful";
|
||||
enhanced3d?: boolean | "subtle" | "realistic";
|
||||
material3d?: Abacus3DMaterial;
|
||||
physics3d?: Abacus3DPhysics;
|
||||
|
||||
// Advanced customization
|
||||
customStyles?: AbacusCustomStyles;
|
||||
|
|
@ -1244,12 +1239,9 @@ interface BeadProps {
|
|||
colorPalette?: string;
|
||||
totalColumns?: number;
|
||||
// 3D Enhancement
|
||||
enhanced3d?: boolean | "subtle" | "realistic" | "delightful";
|
||||
enhanced3d?: boolean | "subtle" | "realistic";
|
||||
material3d?: Abacus3DMaterial;
|
||||
physics3d?: Abacus3DPhysics;
|
||||
columnIndex?: number;
|
||||
mousePosition?: { x: number; y: number };
|
||||
containerBounds?: { x: number; y: number };
|
||||
}
|
||||
|
||||
const Bead: React.FC<BeadProps> = ({
|
||||
|
|
@ -1280,10 +1272,7 @@ const Bead: React.FC<BeadProps> = ({
|
|||
totalColumns = 1,
|
||||
enhanced3d,
|
||||
material3d,
|
||||
physics3d,
|
||||
columnIndex,
|
||||
mousePosition,
|
||||
containerBounds,
|
||||
}) => {
|
||||
// Detect server-side rendering
|
||||
const isServer = typeof window === 'undefined';
|
||||
|
|
@ -1302,22 +1291,6 @@ const Bead: React.FC<BeadProps> = ({
|
|||
config: physicsConfig
|
||||
}));
|
||||
|
||||
// Calculate parallax offset for hover effect
|
||||
const parallaxOffset = React.useMemo(() => {
|
||||
if (enhanced3d === 'delightful' && physics3d?.hoverParallax && mousePosition && containerBounds) {
|
||||
return Abacus3DUtils.calculateParallaxOffset(
|
||||
x,
|
||||
y,
|
||||
mousePosition.x,
|
||||
mousePosition.y,
|
||||
containerBounds.x,
|
||||
containerBounds.y,
|
||||
0.5
|
||||
);
|
||||
}
|
||||
return { x: 0, y: 0, z: 0 };
|
||||
}, [enhanced3d, physics3d?.hoverParallax, mousePosition, containerBounds, x, y]);
|
||||
|
||||
// Arrow pulse animation for urgency indication
|
||||
const [{ arrowPulse }, arrowApi] = useSpring(() => ({
|
||||
arrowPulse: 1,
|
||||
|
|
@ -1427,9 +1400,9 @@ const Bead: React.FC<BeadProps> = ({
|
|||
const renderShape = () => {
|
||||
const halfSize = size / 2;
|
||||
|
||||
// Determine fill - use gradient for realistic/delightful modes, otherwise use color
|
||||
// Determine fill - use gradient for realistic mode, otherwise use color
|
||||
let fillValue = color;
|
||||
if ((enhanced3d === 'realistic' || enhanced3d === 'delightful') && columnIndex !== undefined) {
|
||||
if (enhanced3d === 'realistic' && columnIndex !== undefined) {
|
||||
if (bead.type === 'heaven') {
|
||||
fillValue = `url(#bead-gradient-${columnIndex}-heaven)`;
|
||||
} else {
|
||||
|
|
@ -1495,25 +1468,12 @@ const Bead: React.FC<BeadProps> = ({
|
|||
};
|
||||
|
||||
// Build style object based on animation mode
|
||||
const parallaxEnabled = enhanced3d === 'delightful' && physics3d?.hoverParallax;
|
||||
const beadStyle: any = enableAnimation
|
||||
? {
|
||||
transform: to(
|
||||
[springX, springY],
|
||||
(sx, sy) => {
|
||||
const translate = `translate(${sx - getXOffset() + parallaxOffset.x}px, ${sy - getYOffset() + parallaxOffset.y}px)`;
|
||||
const transforms = [translate];
|
||||
|
||||
// Add parallax Z translation
|
||||
if (parallaxEnabled && parallaxOffset.z > 0) {
|
||||
transforms.push(`translateZ(${parallaxOffset.z}px)`);
|
||||
}
|
||||
|
||||
return transforms.join(' ');
|
||||
},
|
||||
(sx, sy) => `translate(${sx - getXOffset()}px, ${sy - getYOffset()}px)`,
|
||||
),
|
||||
transformOrigin: 'center center',
|
||||
transformStyle: 'preserve-3d',
|
||||
cursor: enableGestures ? "grab" : onClick ? "pointer" : "default",
|
||||
touchAction: "none" as const,
|
||||
transition: "opacity 0.2s ease-in-out",
|
||||
|
|
@ -1624,7 +1584,6 @@ export const AbacusReact: React.FC<AbacusConfig> = ({
|
|||
// 3D enhancement props
|
||||
enhanced3d,
|
||||
material3d,
|
||||
physics3d,
|
||||
// Advanced customization props
|
||||
customStyles,
|
||||
callbacks,
|
||||
|
|
@ -2048,33 +2007,17 @@ export const AbacusReact: React.FC<AbacusConfig> = ({
|
|||
// 3D Enhancement: Calculate container classes
|
||||
const containerClasses = Abacus3DUtils.get3DContainerClasses(
|
||||
enhanced3d,
|
||||
material3d?.lighting,
|
||||
physics3d?.hoverParallax
|
||||
material3d?.lighting
|
||||
);
|
||||
|
||||
// 3D Enhancement: Track mouse position for parallax
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [mousePos, setMousePos] = React.useState({ x: 0, y: 0 });
|
||||
const [containerBounds, setContainerBounds] = React.useState({ x: 0, y: 0 });
|
||||
|
||||
const handleMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
if (enhanced3d === 'delightful' && physics3d?.hoverParallax && containerRef.current) {
|
||||
const rect = containerRef.current.getBoundingClientRect();
|
||||
setMousePos({ x: e.clientX, y: e.clientY });
|
||||
setContainerBounds({ x: rect.left, y: rect.top });
|
||||
}
|
||||
}, [enhanced3d, physics3d?.hoverParallax]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={containerClasses}
|
||||
style={{
|
||||
display: "inline-block",
|
||||
textAlign: "center",
|
||||
position: "relative",
|
||||
}}
|
||||
onMouseMove={handleMouseMove}
|
||||
tabIndex={
|
||||
finalConfig.interactive && finalConfig.showNumbers ? 0 : undefined
|
||||
}
|
||||
|
|
@ -2130,7 +2073,7 @@ export const AbacusReact: React.FC<AbacusConfig> = ({
|
|||
`}</style>
|
||||
|
||||
{/* 3D Enhancement: Material gradients for beads */}
|
||||
{(enhanced3d === 'realistic' || enhanced3d === 'delightful') && material3d && (
|
||||
{enhanced3d === 'realistic' && material3d && (
|
||||
<>
|
||||
{/* Generate gradients for all beads based on material type */}
|
||||
{Array.from({ length: effectiveColumns }, (_, colIndex) => {
|
||||
|
|
@ -2270,7 +2213,7 @@ export const AbacusReact: React.FC<AbacusConfig> = ({
|
|||
className="column-post"
|
||||
/>
|
||||
{/* Wood grain texture overlay for column posts */}
|
||||
{(enhanced3d === 'realistic' || enhanced3d === 'delightful') && material3d?.woodGrain && (
|
||||
{enhanced3d === 'realistic' && material3d?.woodGrain && (
|
||||
<rect
|
||||
x={x - dimensions.rodWidth / 2}
|
||||
y={rodStartY}
|
||||
|
|
@ -2300,7 +2243,7 @@ export const AbacusReact: React.FC<AbacusConfig> = ({
|
|||
className="reckoning-bar"
|
||||
/>
|
||||
{/* Wood grain texture overlay for reckoning bar */}
|
||||
{(enhanced3d === 'realistic' || enhanced3d === 'delightful') && material3d?.woodGrain && (
|
||||
{enhanced3d === 'realistic' && material3d?.woodGrain && (
|
||||
<rect
|
||||
x={dimensions.rodSpacing / 2 - dimensions.beadSize / 2}
|
||||
y={barY}
|
||||
|
|
@ -2497,10 +2440,7 @@ export const AbacusReact: React.FC<AbacusConfig> = ({
|
|||
totalColumns={effectiveColumns}
|
||||
enhanced3d={enhanced3d}
|
||||
material3d={material3d}
|
||||
physics3d={physics3d}
|
||||
columnIndex={colIndex}
|
||||
mousePosition={mousePos}
|
||||
containerBounds={containerBounds}
|
||||
/>
|
||||
);
|
||||
}),
|
||||
|
|
|
|||
Loading…
Reference in New Issue