@wix/interact 1.93.0 → 2.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.js +2 -23
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react.js +15 -0
- package/dist/cjs/react.js.map +1 -0
- package/dist/cjs/web.js +2 -0
- package/dist/cjs/web.js.map +1 -0
- package/dist/es/index.js +8 -0
- package/dist/es/index.js.map +1 -0
- package/dist/es/react.js +650 -0
- package/dist/es/react.js.map +1 -0
- package/dist/es/web.js +56 -0
- package/dist/es/web.js.map +1 -0
- package/dist/index-C8QxOkui.mjs +7940 -0
- package/dist/index-C8QxOkui.mjs.map +1 -0
- package/dist/index-DEPRHaUt.js +18 -0
- package/dist/index-DEPRHaUt.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types/core/Interact.d.ts +17 -7
- package/dist/types/core/Interact.d.ts.map +1 -0
- package/dist/types/core/InteractionController.d.ts +19 -0
- package/dist/types/core/InteractionController.d.ts.map +1 -0
- package/dist/types/core/add.d.ts +4 -3
- package/dist/types/core/add.d.ts.map +1 -0
- package/dist/types/core/css.d.ts +3 -0
- package/dist/types/core/css.d.ts.map +1 -0
- package/dist/types/core/remove.d.ts +3 -1
- package/dist/types/core/remove.d.ts.map +1 -0
- package/dist/types/core/utilities.d.ts +1 -0
- package/dist/types/core/utilities.d.ts.map +1 -0
- package/dist/types/dom/api.d.ts +3 -0
- package/dist/types/dom/api.d.ts.map +1 -0
- package/dist/types/handlers/animationEnd.d.ts +3 -2
- package/dist/types/handlers/animationEnd.d.ts.map +1 -0
- package/dist/types/handlers/click.d.ts +3 -2
- package/dist/types/handlers/click.d.ts.map +1 -0
- package/dist/types/handlers/hover.d.ts +3 -2
- package/dist/types/handlers/hover.d.ts.map +1 -0
- package/dist/types/handlers/index.d.ts +1 -0
- package/dist/types/handlers/index.d.ts.map +1 -0
- package/dist/types/handlers/pointerMove.d.ts +3 -2
- package/dist/types/handlers/pointerMove.d.ts.map +1 -0
- package/dist/types/handlers/utilities.d.ts +1 -0
- package/dist/types/handlers/utilities.d.ts.map +1 -0
- package/dist/types/handlers/viewEnter.d.ts +3 -2
- package/dist/types/handlers/viewEnter.d.ts.map +1 -0
- package/dist/types/handlers/viewProgress.d.ts +4 -3
- package/dist/types/handlers/viewProgress.d.ts.map +1 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/react/Interaction.d.ts +10 -0
- package/dist/types/react/Interaction.d.ts.map +1 -0
- package/dist/types/react/index.d.ts +8 -0
- package/dist/types/react/index.d.ts.map +1 -0
- package/dist/types/react/interactRef.d.ts +3 -0
- package/dist/types/react/interactRef.d.ts.map +1 -0
- package/dist/types/types.d.ts +23 -10
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils.d.ts +2 -1
- package/dist/types/utils.d.ts.map +1 -0
- package/dist/types/{InteractElement.d.ts → web/InteractElement.d.ts} +115 -77
- package/dist/types/web/InteractElement.d.ts.map +1 -0
- package/dist/types/web/defineInteractElement.d.ts +2 -0
- package/dist/types/web/defineInteractElement.d.ts.map +1 -0
- package/dist/types/web/index.d.ts +6 -0
- package/dist/types/web/index.d.ts.map +1 -0
- package/docs/README.md +211 -0
- package/docs/advanced/README.md +164 -0
- package/docs/api/README.md +157 -0
- package/docs/api/element-selection.md +607 -0
- package/docs/api/functions.md +638 -0
- package/docs/api/interact-class.md +663 -0
- package/docs/api/interact-element.md +565 -0
- package/docs/api/interaction-controller.md +450 -0
- package/docs/api/types.md +957 -0
- package/docs/examples/README.md +212 -0
- package/docs/examples/click-interactions.md +977 -0
- package/docs/examples/entrance-animations.md +935 -0
- package/docs/examples/hover-effects.md +930 -0
- package/docs/examples/list-patterns.md +737 -0
- package/docs/guides/README.md +49 -0
- package/docs/guides/conditions-and-media-queries.md +1068 -0
- package/docs/guides/configuration-structure.md +726 -0
- package/docs/guides/custom-elements.md +327 -0
- package/docs/guides/effects-and-animations.md +634 -0
- package/docs/guides/getting-started.md +379 -0
- package/docs/guides/lists-and-dynamic-content.md +713 -0
- package/docs/guides/state-management.md +747 -0
- package/docs/guides/understanding-triggers.md +690 -0
- package/docs/integration/README.md +264 -0
- package/docs/integration/react.md +605 -0
- package/package.json +73 -56
- package/rules/Integration.md +255 -0
- package/rules/click-rules.md +533 -0
- package/rules/full-lean.md +346 -0
- package/rules/hover-rules.md +593 -0
- package/rules/pointermove-rules.md +1341 -0
- package/rules/scroll-list-rules.md +900 -0
- package/rules/viewenter-rules.md +1015 -0
- package/rules/viewprogress-rules.md +1044 -0
- package/dist/cjs/InteractElement.js +0 -163
- package/dist/cjs/InteractElement.js.map +0 -1
- package/dist/cjs/__tests__/interact.spec.js +0 -2094
- package/dist/cjs/__tests__/interact.spec.js.map +0 -1
- package/dist/cjs/__tests__/viewEnter.spec.js +0 -207
- package/dist/cjs/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/cjs/core/Interact.js +0 -257
- package/dist/cjs/core/Interact.js.map +0 -1
- package/dist/cjs/core/add.js +0 -250
- package/dist/cjs/core/add.js.map +0 -1
- package/dist/cjs/core/remove.js +0 -35
- package/dist/cjs/core/remove.js.map +0 -1
- package/dist/cjs/core/utilities.js +0 -16
- package/dist/cjs/core/utilities.js.map +0 -1
- package/dist/cjs/external-types.d.js +0 -2
- package/dist/cjs/external-types.d.js.map +0 -1
- package/dist/cjs/handlers/animationEnd.js +0 -37
- package/dist/cjs/handlers/animationEnd.js.map +0 -1
- package/dist/cjs/handlers/click.js +0 -122
- package/dist/cjs/handlers/click.js.map +0 -1
- package/dist/cjs/handlers/hover.js +0 -147
- package/dist/cjs/handlers/hover.js.map +0 -1
- package/dist/cjs/handlers/index.js +0 -32
- package/dist/cjs/handlers/index.js.map +0 -1
- package/dist/cjs/handlers/pointerMove.js +0 -49
- package/dist/cjs/handlers/pointerMove.js.map +0 -1
- package/dist/cjs/handlers/utilities.js +0 -49
- package/dist/cjs/handlers/utilities.js.map +0 -1
- package/dist/cjs/handlers/viewEnter.js +0 -131
- package/dist/cjs/handlers/viewEnter.js.map +0 -1
- package/dist/cjs/handlers/viewProgress.js +0 -79
- package/dist/cjs/handlers/viewProgress.js.map +0 -1
- package/dist/cjs/test-types.d.js +0 -2
- package/dist/cjs/test-types.d.js.map +0 -1
- package/dist/cjs/types.js +0 -2
- package/dist/cjs/types.js.map +0 -1
- package/dist/cjs/utils.js +0 -98
- package/dist/cjs/utils.js.map +0 -1
- package/dist/esm/InteractElement.js +0 -157
- package/dist/esm/InteractElement.js.map +0 -1
- package/dist/esm/__tests__/interact.spec.js +0 -2102
- package/dist/esm/__tests__/interact.spec.js.map +0 -1
- package/dist/esm/__tests__/viewEnter.spec.js +0 -210
- package/dist/esm/__tests__/viewEnter.spec.js.map +0 -1
- package/dist/esm/core/Interact.js +0 -251
- package/dist/esm/core/Interact.js.map +0 -1
- package/dist/esm/core/add.js +0 -245
- package/dist/esm/core/add.js.map +0 -1
- package/dist/esm/core/remove.js +0 -30
- package/dist/esm/core/remove.js.map +0 -1
- package/dist/esm/core/utilities.js +0 -14
- package/dist/esm/core/utilities.js.map +0 -1
- package/dist/esm/external-types.d.js +0 -2
- package/dist/esm/external-types.d.js.map +0 -1
- package/dist/esm/handlers/animationEnd.js +0 -33
- package/dist/esm/handlers/animationEnd.js.map +0 -1
- package/dist/esm/handlers/click.js +0 -122
- package/dist/esm/handlers/click.js.map +0 -1
- package/dist/esm/handlers/hover.js +0 -147
- package/dist/esm/handlers/hover.js.map +0 -1
- package/dist/esm/handlers/index.js +0 -27
- package/dist/esm/handlers/index.js.map +0 -1
- package/dist/esm/handlers/pointerMove.js +0 -48
- package/dist/esm/handlers/pointerMove.js.map +0 -1
- package/dist/esm/handlers/utilities.js +0 -43
- package/dist/esm/handlers/utilities.js.map +0 -1
- package/dist/esm/handlers/viewEnter.js +0 -133
- package/dist/esm/handlers/viewEnter.js.map +0 -1
- package/dist/esm/handlers/viewProgress.js +0 -75
- package/dist/esm/handlers/viewProgress.js.map +0 -1
- package/dist/esm/index.js +0 -5
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/test-types.d.js +0 -2
- package/dist/esm/test-types.d.js.map +0 -1
- package/dist/esm/types.js +0 -2
- package/dist/esm/types.js.map +0 -1
- package/dist/esm/utils.js +0 -92
- package/dist/esm/utils.js.map +0 -1
- package/dist/types/__tests__/interact.spec.d.ts +0 -1
- package/dist/types/__tests__/viewEnter.spec.d.ts +0 -0
|
@@ -0,0 +1,1341 @@
|
|
|
1
|
+
# PointerMove Trigger Rules for @wix/interact
|
|
2
|
+
|
|
3
|
+
These rules help generate pointer-driven interactions using the `@wix/interact` library. PointerMove triggers create real-time animations that respond to mouse movement over elements, perfect for 3D effects, cursor followers, and interactive cards.
|
|
4
|
+
|
|
5
|
+
## Core Concepts
|
|
6
|
+
|
|
7
|
+
### Effect Types for PointerMove
|
|
8
|
+
|
|
9
|
+
**IMPORTANT**: The `pointerMove` trigger provides 2D progress (x and y coordinates), which is incompatible with linear `keyframeEffect` animations. Only use:
|
|
10
|
+
|
|
11
|
+
1. **`namedEffect`** (Preferred): Pre-built mouse presets from `@wix/motion` that handle 2D progress internally
|
|
12
|
+
2. **`customEffect`** (Advanced): Custom function receiving the 2D progress object for full control
|
|
13
|
+
|
|
14
|
+
**Never use `keyframeEffect` with `pointerMove`** - keyframes require linear 0-1 progress and cannot handle 2D coordinates.
|
|
15
|
+
|
|
16
|
+
### Hit Area Configuration (`hitArea`)
|
|
17
|
+
|
|
18
|
+
The `hitArea` parameter determines where mouse movement is tracked:
|
|
19
|
+
|
|
20
|
+
| Value | Behavior | Best For |
|
|
21
|
+
|-------|----------|----------|
|
|
22
|
+
| `'self'` | Tracks mouse within the source element's bounds only | Local hover effects, card interactions |
|
|
23
|
+
| `'root'` | Tracks mouse anywhere in the viewport (document root) | Global cursor followers, ambient effects |
|
|
24
|
+
|
|
25
|
+
### Progress Object Structure (for `customEffect`)
|
|
26
|
+
|
|
27
|
+
When using `customEffect` with `pointerMove`, the progress parameter is an object:
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
type Progress = {
|
|
31
|
+
x: number; // 0-1: horizontal position (0 = left edge, 1 = right edge)
|
|
32
|
+
y: number; // 0-1: vertical position (0 = top edge, 1 = bottom edge)
|
|
33
|
+
v?: { // Velocity (optional)
|
|
34
|
+
x: number; // Horizontal velocity
|
|
35
|
+
y: number; // Vertical velocity
|
|
36
|
+
};
|
|
37
|
+
active?: boolean; // Whether mouse is currently in the hit area
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Centering with `centeredToTarget`
|
|
42
|
+
|
|
43
|
+
Controls how the progress range is calculated:
|
|
44
|
+
|
|
45
|
+
| Value | Behavior | Use When |
|
|
46
|
+
|-------|----------|----------|
|
|
47
|
+
| `true` | Centers the coordinate range at the target element | Source and target are different elements |
|
|
48
|
+
| `false` | Uses source element bounds for calculations | Cursor followers, global effects |
|
|
49
|
+
|
|
50
|
+
## Rule 1: Single Element Pointer Effects with 3D Named Effects
|
|
51
|
+
|
|
52
|
+
**Use Case**: Interactive 3D transformations on individual elements that respond to mouse position (e.g., card tilting, 3D product showcases, interactive buttons)
|
|
53
|
+
|
|
54
|
+
**When to Apply**:
|
|
55
|
+
- For interactive card hover effects
|
|
56
|
+
- When creating 3D product showcases
|
|
57
|
+
- For engaging button interactions
|
|
58
|
+
- When building interactive UI elements that respond to mouse movement
|
|
59
|
+
|
|
60
|
+
**Pattern**:
|
|
61
|
+
```typescript
|
|
62
|
+
{
|
|
63
|
+
key: '[SOURCE_KEY]',
|
|
64
|
+
trigger: 'pointerMove',
|
|
65
|
+
params: {
|
|
66
|
+
hitArea: '[HIT_AREA]'
|
|
67
|
+
},
|
|
68
|
+
effects: [
|
|
69
|
+
{
|
|
70
|
+
key: '[TARGET_KEY]',
|
|
71
|
+
namedEffect: {
|
|
72
|
+
type: '[3D_EFFECT_TYPE]',
|
|
73
|
+
[EFFECT_PROPERTIES]
|
|
74
|
+
},
|
|
75
|
+
centeredToTarget: [CENTERED_TO_TARGET],
|
|
76
|
+
effectId: '[UNIQUE_EFFECT_ID]'
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**Variables**:
|
|
83
|
+
- `[SOURCE_KEY]`: Unique identifier for source element that tracks mouse movement
|
|
84
|
+
- `[TARGET_KEY]`: Unique identifier for target element to animate (can be same as source or different)
|
|
85
|
+
- `[HIT_AREA]`: 'self' (mouse within source element) or 'root' (mouse anywhere in viewport)
|
|
86
|
+
- `[3D_EFFECT_TYPE]`: 'Tilt3DMouse', 'Track3DMouse', 'SwivelMouse'
|
|
87
|
+
- `[EFFECT_PROPERTIES]`: Named effect specific properties (angle, perspective, power, etc.)
|
|
88
|
+
- `[CENTERED_TO_TARGET]`: true (center range at target) or false (use source element bounds)
|
|
89
|
+
- `[UNIQUE_EFFECT_ID]`: Optional unique identifier
|
|
90
|
+
|
|
91
|
+
**Example - Interactive Product Card**:
|
|
92
|
+
```typescript
|
|
93
|
+
{
|
|
94
|
+
key: 'product-card',
|
|
95
|
+
trigger: 'pointerMove',
|
|
96
|
+
params: {
|
|
97
|
+
hitArea: 'self'
|
|
98
|
+
},
|
|
99
|
+
effects: [
|
|
100
|
+
{
|
|
101
|
+
key: 'product-card',
|
|
102
|
+
namedEffect: {
|
|
103
|
+
type: 'Tilt3DMouse',
|
|
104
|
+
angle: 15,
|
|
105
|
+
perspective: 1000,
|
|
106
|
+
power: 'medium'
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Rule 2: Single Element Pointer Effects with Movement Named Effects
|
|
116
|
+
|
|
117
|
+
**Use Case**: Cursor-following and position-tracking effects on individual elements (e.g., floating elements, cursor followers, responsive decorations)
|
|
118
|
+
|
|
119
|
+
**When to Apply**:
|
|
120
|
+
- For cursor-following elements
|
|
121
|
+
- When creating floating responsive decorations
|
|
122
|
+
- For interactive element positioning
|
|
123
|
+
- When building mouse-aware UI components
|
|
124
|
+
|
|
125
|
+
**Pattern**:
|
|
126
|
+
```typescript
|
|
127
|
+
{
|
|
128
|
+
key: '[SOURCE_KEY]',
|
|
129
|
+
trigger: 'pointerMove',
|
|
130
|
+
params: {
|
|
131
|
+
hitArea: '[HIT_AREA]'
|
|
132
|
+
},
|
|
133
|
+
effects: [
|
|
134
|
+
{
|
|
135
|
+
key: '[TARGET_KEY]',
|
|
136
|
+
namedEffect: {
|
|
137
|
+
type: '[MOVEMENT_EFFECT_TYPE]',
|
|
138
|
+
distance: { value: [DISTANCE_VALUE], type: '[DISTANCE_UNIT]' },
|
|
139
|
+
axis: '[AXIS_CONSTRAINT]',
|
|
140
|
+
power: '[POWER_LEVEL]'
|
|
141
|
+
},
|
|
142
|
+
centeredToTarget: [CENTERED_TO_TARGET],
|
|
143
|
+
effectId: '[UNIQUE_EFFECT_ID]'
|
|
144
|
+
}
|
|
145
|
+
]
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
**Variables**:
|
|
150
|
+
- `[MOVEMENT_EFFECT_TYPE]`: 'TrackMouse', 'AiryMouse', 'BounceMouse'
|
|
151
|
+
- `[DISTANCE_VALUE]`: Numeric value for movement distance
|
|
152
|
+
- `[DISTANCE_UNIT]`: 'px', 'percentage', 'vw', 'vh'
|
|
153
|
+
- `[AXIS_CONSTRAINT]`: 'both', 'horizontal', 'vertical'
|
|
154
|
+
- `[POWER_LEVEL]`: 'soft', 'medium', 'hard'
|
|
155
|
+
- Other variables same as Rule 1
|
|
156
|
+
|
|
157
|
+
**Example - Cursor Follower Element**:
|
|
158
|
+
```typescript
|
|
159
|
+
{
|
|
160
|
+
key: 'cursor-follower',
|
|
161
|
+
trigger: 'pointerMove',
|
|
162
|
+
params: {
|
|
163
|
+
hitArea: 'root'
|
|
164
|
+
},
|
|
165
|
+
effects: [
|
|
166
|
+
{
|
|
167
|
+
namedEffect: {
|
|
168
|
+
type: 'TrackMouse',
|
|
169
|
+
distance: { value: 50, type: 'percentage' },
|
|
170
|
+
axis: 'both',
|
|
171
|
+
power: 'medium'
|
|
172
|
+
},
|
|
173
|
+
centeredToTarget: false
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**Example - Floating Decoration**:
|
|
180
|
+
```typescript
|
|
181
|
+
{
|
|
182
|
+
key: 'hero-section',
|
|
183
|
+
trigger: 'pointerMove',
|
|
184
|
+
params: {
|
|
185
|
+
hitArea: 'self'
|
|
186
|
+
},
|
|
187
|
+
effects: [
|
|
188
|
+
{
|
|
189
|
+
key: 'floating-element',
|
|
190
|
+
namedEffect: {
|
|
191
|
+
type: 'AiryMouse',
|
|
192
|
+
distance: { value: 30, type: 'px' },
|
|
193
|
+
axis: 'both',
|
|
194
|
+
power: 'soft'
|
|
195
|
+
},
|
|
196
|
+
centeredToTarget: true,
|
|
197
|
+
effectId: 'hero-float'
|
|
198
|
+
}
|
|
199
|
+
]
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Rule 3: Single Element Pointer Effects with Scale Named Effects
|
|
206
|
+
|
|
207
|
+
**Use Case**: Dynamic scaling and deformation effects on individual elements based on mouse position (e.g., interactive scaling, organic transformations, blob effects)
|
|
208
|
+
|
|
209
|
+
**When to Apply**:
|
|
210
|
+
- For interactive scaling buttons
|
|
211
|
+
- When creating organic blob-like interactions
|
|
212
|
+
- For dynamic size responsive elements
|
|
213
|
+
- When building creative morphing interfaces
|
|
214
|
+
|
|
215
|
+
**Pattern**:
|
|
216
|
+
```typescript
|
|
217
|
+
{
|
|
218
|
+
key: '[SOURCE_KEY]',
|
|
219
|
+
trigger: 'pointerMove',
|
|
220
|
+
params: {
|
|
221
|
+
hitArea: '[HIT_AREA]'
|
|
222
|
+
},
|
|
223
|
+
effects: [
|
|
224
|
+
{
|
|
225
|
+
key: '[TARGET_KEY]',
|
|
226
|
+
namedEffect: {
|
|
227
|
+
type: '[SCALE_EFFECT_TYPE]',
|
|
228
|
+
[SCALE_PROPERTIES]
|
|
229
|
+
},
|
|
230
|
+
centeredToTarget: [CENTERED_TO_TARGET],
|
|
231
|
+
effectId: '[UNIQUE_EFFECT_ID]'
|
|
232
|
+
}
|
|
233
|
+
]
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
**Variables**:
|
|
238
|
+
- `[SCALE_EFFECT_TYPE]`: 'ScaleMouse', 'BlobMouse', 'SkewMouse'
|
|
239
|
+
- `[SCALE_PROPERTIES]`: Effect-specific properties (scale, distance, axis, power)
|
|
240
|
+
- Other variables same as Rule 1
|
|
241
|
+
|
|
242
|
+
**Example - Interactive Scale Button**:
|
|
243
|
+
```typescript
|
|
244
|
+
{
|
|
245
|
+
key: 'scale-button',
|
|
246
|
+
trigger: 'pointerMove',
|
|
247
|
+
params: {
|
|
248
|
+
hitArea: 'self'
|
|
249
|
+
},
|
|
250
|
+
effects: [
|
|
251
|
+
{
|
|
252
|
+
key: 'scale-button',
|
|
253
|
+
namedEffect: {
|
|
254
|
+
type: 'ScaleMouse',
|
|
255
|
+
scale: 1.1,
|
|
256
|
+
distance: { value: 100, type: 'px' },
|
|
257
|
+
axis: 'both',
|
|
258
|
+
power: 'medium'
|
|
259
|
+
},
|
|
260
|
+
centeredToTarget: true
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Example - Organic Blob Effect**:
|
|
267
|
+
```typescript
|
|
268
|
+
{
|
|
269
|
+
key: 'blob-container',
|
|
270
|
+
trigger: 'pointerMove',
|
|
271
|
+
params: {
|
|
272
|
+
hitArea: 'self'
|
|
273
|
+
},
|
|
274
|
+
effects: [
|
|
275
|
+
{
|
|
276
|
+
key: 'blob-shape',
|
|
277
|
+
namedEffect: {
|
|
278
|
+
type: 'BlobMouse',
|
|
279
|
+
intensity: 0.8,
|
|
280
|
+
smoothness: 0.6,
|
|
281
|
+
power: 'medium'
|
|
282
|
+
},
|
|
283
|
+
effectId: 'blob-morph'
|
|
284
|
+
}
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
---
|
|
290
|
+
|
|
291
|
+
## Rule 4: Single Element Pointer Effects with Visual Named Effects
|
|
292
|
+
|
|
293
|
+
**Use Case**: Visual effect transformations on individual elements based on mouse position (e.g., motion blur, rotation effects, visual filters)
|
|
294
|
+
|
|
295
|
+
**When to Apply**:
|
|
296
|
+
- For creative visual interfaces
|
|
297
|
+
- When adding motion blur to interactions
|
|
298
|
+
- For rotation-based mouse effects
|
|
299
|
+
- When creating dynamic visual feedback
|
|
300
|
+
|
|
301
|
+
**Pattern**:
|
|
302
|
+
```typescript
|
|
303
|
+
{
|
|
304
|
+
key: '[SOURCE_KEY]',
|
|
305
|
+
trigger: 'pointerMove',
|
|
306
|
+
params: {
|
|
307
|
+
hitArea: '[HIT_AREA]'
|
|
308
|
+
},
|
|
309
|
+
effects: [
|
|
310
|
+
{
|
|
311
|
+
key: '[TARGET_KEY]',
|
|
312
|
+
namedEffect: {
|
|
313
|
+
type: '[VISUAL_EFFECT_TYPE]',
|
|
314
|
+
[VISUAL_PROPERTIES]
|
|
315
|
+
},
|
|
316
|
+
centeredToTarget: [CENTERED_TO_TARGET],
|
|
317
|
+
effectId: '[UNIQUE_EFFECT_ID]'
|
|
318
|
+
}
|
|
319
|
+
]
|
|
320
|
+
}
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Variables**:
|
|
324
|
+
- `[VISUAL_EFFECT_TYPE]`: 'BlurMouse', 'SpinMouse'
|
|
325
|
+
- `[VISUAL_PROPERTIES]`: Effect-specific properties (blur amount, rotation speed, power)
|
|
326
|
+
- Other variables same as Rule 1
|
|
327
|
+
|
|
328
|
+
**Example - Motion Blur Card**:
|
|
329
|
+
```typescript
|
|
330
|
+
{
|
|
331
|
+
key: 'motion-card',
|
|
332
|
+
trigger: 'pointerMove',
|
|
333
|
+
params: {
|
|
334
|
+
hitArea: 'self'
|
|
335
|
+
},
|
|
336
|
+
effects: [
|
|
337
|
+
{
|
|
338
|
+
key: 'motion-card',
|
|
339
|
+
namedEffect: {
|
|
340
|
+
type: 'BlurMouse',
|
|
341
|
+
blurAmount: 5,
|
|
342
|
+
motionIntensity: 0.7,
|
|
343
|
+
power: 'medium'
|
|
344
|
+
},
|
|
345
|
+
centeredToTarget: true
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
**Example - Spinning Element**:
|
|
352
|
+
```typescript
|
|
353
|
+
{
|
|
354
|
+
key: 'spin-trigger',
|
|
355
|
+
trigger: 'pointerMove',
|
|
356
|
+
params: {
|
|
357
|
+
hitArea: 'self'
|
|
358
|
+
},
|
|
359
|
+
effects: [
|
|
360
|
+
{
|
|
361
|
+
key: 'spinning-icon',
|
|
362
|
+
namedEffect: {
|
|
363
|
+
type: 'SpinMouse',
|
|
364
|
+
rotationSpeed: 0.5,
|
|
365
|
+
direction: 'clockwise',
|
|
366
|
+
power: 'soft'
|
|
367
|
+
},
|
|
368
|
+
centeredToTarget: false,
|
|
369
|
+
effectId: 'icon-spin'
|
|
370
|
+
}
|
|
371
|
+
]
|
|
372
|
+
}
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
## Rule 5: Multi-Element Pointer Parallax Effects with Named Effects
|
|
378
|
+
|
|
379
|
+
**Use Case**: Coordinated pointer-driven animations across multiple elements creating layered parallax effects (e.g., multi-layer backgrounds, depth effects, coordinated element responses)
|
|
380
|
+
|
|
381
|
+
**When to Apply**:
|
|
382
|
+
- For multi-layer background effects
|
|
383
|
+
- When creating depth and parallax interactions
|
|
384
|
+
- For coordinated UI element responses
|
|
385
|
+
- When building immersive pointer-driven experiences
|
|
386
|
+
|
|
387
|
+
**Pattern**:
|
|
388
|
+
```typescript
|
|
389
|
+
{
|
|
390
|
+
key: '[CONTAINER_KEY]',
|
|
391
|
+
trigger: 'pointerMove',
|
|
392
|
+
params: {
|
|
393
|
+
hitArea: '[HIT_AREA]'
|
|
394
|
+
},
|
|
395
|
+
effects: [
|
|
396
|
+
{
|
|
397
|
+
key: '[BACKGROUND_LAYER_KEY]',
|
|
398
|
+
namedEffect: {
|
|
399
|
+
type: '[BACKGROUND_EFFECT_TYPE]',
|
|
400
|
+
distance: { value: [BACKGROUND_DISTANCE], type: '[DISTANCE_UNIT]' },
|
|
401
|
+
power: '[BACKGROUND_POWER]'
|
|
402
|
+
},
|
|
403
|
+
centeredToTarget: [CENTERED_TO_TARGET]
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
key: '[MIDGROUND_LAYER_KEY]',
|
|
407
|
+
namedEffect: {
|
|
408
|
+
type: '[MIDGROUND_EFFECT_TYPE]',
|
|
409
|
+
distance: { value: [MIDGROUND_DISTANCE], type: '[DISTANCE_UNIT]' },
|
|
410
|
+
power: '[MIDGROUND_POWER]'
|
|
411
|
+
},
|
|
412
|
+
centeredToTarget: [CENTERED_TO_TARGET]
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
key: '[FOREGROUND_LAYER_KEY]',
|
|
416
|
+
namedEffect: {
|
|
417
|
+
type: '[FOREGROUND_EFFECT_TYPE]',
|
|
418
|
+
distance: { value: [FOREGROUND_DISTANCE], type: '[DISTANCE_UNIT]' },
|
|
419
|
+
power: '[FOREGROUND_POWER]'
|
|
420
|
+
},
|
|
421
|
+
centeredToTarget: [CENTERED_TO_TARGET]
|
|
422
|
+
}
|
|
423
|
+
]
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
**Variables**:
|
|
428
|
+
- `[CONTAINER_KEY]`: Unique identifier for container element tracking mouse
|
|
429
|
+
- `[*_LAYER_KEY]`: Unique identifier for different layer elements
|
|
430
|
+
- `[*_EFFECT_TYPE]`: Named effects for each layer (typically movement effects)
|
|
431
|
+
- `[*_DISTANCE]`: Movement distance for each layer (creating depth)
|
|
432
|
+
- `[*_POWER]`: Power level for each layer response
|
|
433
|
+
- Other variables same as previous rules
|
|
434
|
+
|
|
435
|
+
**Example - Parallax Card Layers**:
|
|
436
|
+
```typescript
|
|
437
|
+
{
|
|
438
|
+
key: 'parallax-card',
|
|
439
|
+
trigger: 'pointerMove',
|
|
440
|
+
params: {
|
|
441
|
+
hitArea: 'self'
|
|
442
|
+
},
|
|
443
|
+
effects: [
|
|
444
|
+
{
|
|
445
|
+
key: 'bg-layer',
|
|
446
|
+
namedEffect: {
|
|
447
|
+
type: 'AiryMouse',
|
|
448
|
+
distance: { value: 15, type: 'px' },
|
|
449
|
+
axis: 'both',
|
|
450
|
+
power: 'soft'
|
|
451
|
+
},
|
|
452
|
+
centeredToTarget: true
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
key: 'mid-layer',
|
|
456
|
+
namedEffect: {
|
|
457
|
+
type: 'TrackMouse',
|
|
458
|
+
distance: { value: 25, type: 'px' },
|
|
459
|
+
axis: 'both',
|
|
460
|
+
power: 'medium'
|
|
461
|
+
},
|
|
462
|
+
centeredToTarget: true
|
|
463
|
+
},
|
|
464
|
+
{
|
|
465
|
+
key: 'fg-layer',
|
|
466
|
+
namedEffect: {
|
|
467
|
+
type: 'BounceMouse',
|
|
468
|
+
distance: { value: 35, type: 'px' },
|
|
469
|
+
axis: 'both',
|
|
470
|
+
power: 'medium'
|
|
471
|
+
},
|
|
472
|
+
centeredToTarget: true
|
|
473
|
+
}
|
|
474
|
+
]
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Example - Multi-Layer Hero Section**:
|
|
479
|
+
```typescript
|
|
480
|
+
{
|
|
481
|
+
key: 'hero-container',
|
|
482
|
+
trigger: 'pointerMove',
|
|
483
|
+
params: {
|
|
484
|
+
hitArea: 'self'
|
|
485
|
+
},
|
|
486
|
+
effects: [
|
|
487
|
+
{
|
|
488
|
+
key: 'hero-bg',
|
|
489
|
+
namedEffect: {
|
|
490
|
+
type: 'AiryMouse',
|
|
491
|
+
distance: { value: 20, type: 'px' },
|
|
492
|
+
axis: 'both',
|
|
493
|
+
power: 'soft'
|
|
494
|
+
},
|
|
495
|
+
centeredToTarget: true
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
key: 'hero-content',
|
|
499
|
+
namedEffect: {
|
|
500
|
+
type: 'TrackMouse',
|
|
501
|
+
distance: { value: 40, type: 'px' },
|
|
502
|
+
axis: 'horizontal',
|
|
503
|
+
power: 'medium'
|
|
504
|
+
},
|
|
505
|
+
centeredToTarget: true
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
key: 'hero-decorations',
|
|
509
|
+
namedEffect: {
|
|
510
|
+
type: 'ScaleMouse',
|
|
511
|
+
scale: 1.05,
|
|
512
|
+
distance: { value: 60, type: 'px' },
|
|
513
|
+
power: 'medium'
|
|
514
|
+
},
|
|
515
|
+
centeredToTarget: true
|
|
516
|
+
}
|
|
517
|
+
]
|
|
518
|
+
}
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## Rule 6: Coordinated Group Pointer Effects with Named Effects
|
|
524
|
+
|
|
525
|
+
**Use Case**: Synchronized pointer-driven animations across related elements with different responses (e.g., card grids, navigation menus, interactive galleries)
|
|
526
|
+
|
|
527
|
+
**When to Apply**:
|
|
528
|
+
- For interactive card grids
|
|
529
|
+
- When building responsive navigation systems
|
|
530
|
+
- For gallery hover effects
|
|
531
|
+
- When creating coordinated interface responses
|
|
532
|
+
|
|
533
|
+
**Pattern**:
|
|
534
|
+
```typescript
|
|
535
|
+
{
|
|
536
|
+
key: '[CONTAINER_KEY]',
|
|
537
|
+
trigger: 'pointerMove',
|
|
538
|
+
params: {
|
|
539
|
+
hitArea: '[HIT_AREA]'
|
|
540
|
+
},
|
|
541
|
+
effects: [
|
|
542
|
+
{
|
|
543
|
+
key: '[PRIMARY_ELEMENTS_KEY]',
|
|
544
|
+
namedEffect: {
|
|
545
|
+
type: '[PRIMARY_EFFECT_TYPE]',
|
|
546
|
+
[PRIMARY_EFFECT_PROPERTIES]
|
|
547
|
+
},
|
|
548
|
+
centeredToTarget: [PRIMARY_CENTERED]
|
|
549
|
+
},
|
|
550
|
+
{
|
|
551
|
+
key: '[SECONDARY_ELEMENTS_KEY]',
|
|
552
|
+
namedEffect: {
|
|
553
|
+
type: '[SECONDARY_EFFECT_TYPE]',
|
|
554
|
+
[SECONDARY_EFFECT_PROPERTIES]
|
|
555
|
+
},
|
|
556
|
+
centeredToTarget: [SECONDARY_CENTERED]
|
|
557
|
+
}
|
|
558
|
+
]
|
|
559
|
+
}
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
**Variables**:
|
|
563
|
+
- `[PRIMARY_ELEMENTS_KEY]`: Unique identifier for primary responsive elements
|
|
564
|
+
- `[SECONDARY_ELEMENTS_KEY]`: Unique identifier for secondary responsive elements
|
|
565
|
+
- `[PRIMARY_EFFECT_TYPE]`: Named effect for primary elements
|
|
566
|
+
- `[SECONDARY_EFFECT_TYPE]`: Named effect for secondary elements
|
|
567
|
+
- `[*_EFFECT_PROPERTIES]`: Properties specific to each effect type
|
|
568
|
+
- `[*_CENTERED]`: Centering configuration for each element group
|
|
569
|
+
- Other variables same as previous rules
|
|
570
|
+
|
|
571
|
+
**Example - Interactive Card Grid**:
|
|
572
|
+
```typescript
|
|
573
|
+
{
|
|
574
|
+
key: 'card-grid',
|
|
575
|
+
trigger: 'pointerMove',
|
|
576
|
+
params: {
|
|
577
|
+
hitArea: 'self'
|
|
578
|
+
},
|
|
579
|
+
effects: [
|
|
580
|
+
{
|
|
581
|
+
key: 'grid-card',
|
|
582
|
+
namedEffect: {
|
|
583
|
+
type: 'Tilt3DMouse',
|
|
584
|
+
angle: 12,
|
|
585
|
+
perspective: 1000,
|
|
586
|
+
power: 'soft'
|
|
587
|
+
},
|
|
588
|
+
centeredToTarget: true
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
key: 'card-shadow',
|
|
592
|
+
namedEffect: {
|
|
593
|
+
type: 'AiryMouse',
|
|
594
|
+
distance: { value: 20, type: 'px' },
|
|
595
|
+
axis: 'both',
|
|
596
|
+
power: 'soft'
|
|
597
|
+
},
|
|
598
|
+
centeredToTarget: true
|
|
599
|
+
}
|
|
600
|
+
]
|
|
601
|
+
}
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
**Example - Navigation Menu Response**:
|
|
605
|
+
```typescript
|
|
606
|
+
{
|
|
607
|
+
key: 'nav-container',
|
|
608
|
+
trigger: 'pointerMove',
|
|
609
|
+
params: {
|
|
610
|
+
hitArea: 'self'
|
|
611
|
+
},
|
|
612
|
+
effects: [
|
|
613
|
+
{
|
|
614
|
+
key: 'nav-item',
|
|
615
|
+
namedEffect: {
|
|
616
|
+
type: 'ScaleMouse',
|
|
617
|
+
scale: 1.05,
|
|
618
|
+
distance: { value: 80, type: 'px' },
|
|
619
|
+
power: 'medium'
|
|
620
|
+
},
|
|
621
|
+
centeredToTarget: true
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
key: 'nav-indicator',
|
|
625
|
+
namedEffect: {
|
|
626
|
+
type: 'TrackMouse',
|
|
627
|
+
distance: { value: 15, type: 'px' },
|
|
628
|
+
axis: 'horizontal',
|
|
629
|
+
power: 'hard'
|
|
630
|
+
},
|
|
631
|
+
centeredToTarget: false
|
|
632
|
+
}
|
|
633
|
+
]
|
|
634
|
+
}
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
---
|
|
638
|
+
|
|
639
|
+
## Rule 7: Global Cursor Follower Effects with Named Effects
|
|
640
|
+
|
|
641
|
+
**Use Case**: Page-wide cursor following elements that respond to mouse movement anywhere (e.g., custom cursors, global decorative followers, interactive overlays)
|
|
642
|
+
|
|
643
|
+
**When to Apply**:
|
|
644
|
+
- For custom cursor implementations
|
|
645
|
+
- When creating global interactive overlays
|
|
646
|
+
- For page-wide decorative followers
|
|
647
|
+
- When building immersive cursor experiences
|
|
648
|
+
|
|
649
|
+
**Pattern**:
|
|
650
|
+
```typescript
|
|
651
|
+
{
|
|
652
|
+
key: '[FOLLOWER_KEY]',
|
|
653
|
+
trigger: 'pointerMove',
|
|
654
|
+
params: {
|
|
655
|
+
hitArea: 'root'
|
|
656
|
+
},
|
|
657
|
+
effects: [
|
|
658
|
+
{
|
|
659
|
+
namedEffect: {
|
|
660
|
+
type: '[FOLLOWER_EFFECT_TYPE]',
|
|
661
|
+
distance: { value: [FOLLOWER_DISTANCE], type: '[DISTANCE_UNIT]' },
|
|
662
|
+
[FOLLOWER_PROPERTIES]
|
|
663
|
+
},
|
|
664
|
+
centeredToTarget: false,
|
|
665
|
+
effectId: '[FOLLOWER_EFFECT_ID]'
|
|
666
|
+
}
|
|
667
|
+
]
|
|
668
|
+
}
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
**Variables**:
|
|
672
|
+
- `[FOLLOWER_KEY]`: Unique identifier for cursor follower element
|
|
673
|
+
- `[FOLLOWER_EFFECT_TYPE]`: 'TrackMouse', 'AiryMouse', 'BounceMouse'
|
|
674
|
+
- `[FOLLOWER_DISTANCE]`: Distance/lag for follower (0 for perfect following)
|
|
675
|
+
- `[FOLLOWER_PROPERTIES]`: Additional effect properties
|
|
676
|
+
- `[FOLLOWER_EFFECT_ID]`: Unique identifier for the follower effect
|
|
677
|
+
- Other variables same as previous rules
|
|
678
|
+
|
|
679
|
+
**Example - Custom Cursor Follower**:
|
|
680
|
+
```typescript
|
|
681
|
+
{
|
|
682
|
+
key: 'custom-cursor',
|
|
683
|
+
trigger: 'pointerMove',
|
|
684
|
+
params: {
|
|
685
|
+
hitArea: 'root'
|
|
686
|
+
},
|
|
687
|
+
effects: [
|
|
688
|
+
{
|
|
689
|
+
namedEffect: {
|
|
690
|
+
type: 'TrackMouse',
|
|
691
|
+
distance: { value: 0, type: 'px' },
|
|
692
|
+
axis: 'both',
|
|
693
|
+
power: 'hard'
|
|
694
|
+
},
|
|
695
|
+
centeredToTarget: false,
|
|
696
|
+
effectId: 'global-cursor'
|
|
697
|
+
}
|
|
698
|
+
]
|
|
699
|
+
}
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
**Example - Floating Decoration Follower**:
|
|
703
|
+
```typescript
|
|
704
|
+
{
|
|
705
|
+
key: 'floating-decoration',
|
|
706
|
+
trigger: 'pointerMove',
|
|
707
|
+
params: {
|
|
708
|
+
hitArea: 'root'
|
|
709
|
+
},
|
|
710
|
+
effects: [
|
|
711
|
+
{
|
|
712
|
+
namedEffect: {
|
|
713
|
+
type: 'AiryMouse',
|
|
714
|
+
distance: { value: 50, type: 'px' },
|
|
715
|
+
axis: 'both',
|
|
716
|
+
power: 'soft'
|
|
717
|
+
},
|
|
718
|
+
centeredToTarget: false,
|
|
719
|
+
effectId: 'decoration-follower'
|
|
720
|
+
}
|
|
721
|
+
]
|
|
722
|
+
}
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
## Rule 8: Custom Pointer Effects with customEffect
|
|
728
|
+
|
|
729
|
+
**Use Case**: When you need full control over pointer-driven animations that cannot be achieved with named effects, such as custom physics, complex multi-property animations, or unique visual transformations.
|
|
730
|
+
|
|
731
|
+
**When to Apply**:
|
|
732
|
+
- For custom physics-based animations
|
|
733
|
+
- When creating unique visual effects not covered by named effects
|
|
734
|
+
- When controlling WebGL/WebGPU effects or other JavaScript controlled effects
|
|
735
|
+
- For complex DOM manipulations based on mouse position
|
|
736
|
+
- When implementing grid-based or particle effects
|
|
737
|
+
- For animations requiring access to velocity data
|
|
738
|
+
|
|
739
|
+
**IMPORTANT**: Only use `customEffect` when `namedEffect` cannot achieve the desired result. Named effects are optimized and GPU-friendly.
|
|
740
|
+
|
|
741
|
+
**Pattern - Basic customEffect**:
|
|
742
|
+
```typescript
|
|
743
|
+
{
|
|
744
|
+
key: '[SOURCE_KEY]',
|
|
745
|
+
trigger: 'pointerMove',
|
|
746
|
+
params: {
|
|
747
|
+
hitArea: '[HIT_AREA]'
|
|
748
|
+
},
|
|
749
|
+
effects: [
|
|
750
|
+
{
|
|
751
|
+
key: '[TARGET_KEY]',
|
|
752
|
+
customEffect: (element, progress) => {
|
|
753
|
+
// progress.x: 0-1 horizontal position
|
|
754
|
+
// progress.y: 0-1 vertical position
|
|
755
|
+
// progress.v: { x, y } velocity (optional)
|
|
756
|
+
// progress.active: boolean (optional)
|
|
757
|
+
|
|
758
|
+
[CUSTOM_ANIMATION_LOGIC]
|
|
759
|
+
},
|
|
760
|
+
centeredToTarget: [CENTERED_TO_TARGET]
|
|
761
|
+
}
|
|
762
|
+
]
|
|
763
|
+
}
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
**Variables**:
|
|
767
|
+
- `[SOURCE_KEY]`: Unique identifier for source element tracking mouse movement
|
|
768
|
+
- `[TARGET_KEY]`: Unique identifier for target element to animate
|
|
769
|
+
- `[HIT_AREA]`: 'self' or 'root'
|
|
770
|
+
- `[CUSTOM_ANIMATION_LOGIC]`: Your custom animation code using the progress object
|
|
771
|
+
- `[CENTERED_TO_TARGET]`: true or false
|
|
772
|
+
|
|
773
|
+
**Example - Custom Rotation Based on Mouse Position**:
|
|
774
|
+
```typescript
|
|
775
|
+
{
|
|
776
|
+
key: 'rotation-container',
|
|
777
|
+
trigger: 'pointerMove',
|
|
778
|
+
params: {
|
|
779
|
+
hitArea: 'self'
|
|
780
|
+
},
|
|
781
|
+
effects: [
|
|
782
|
+
{
|
|
783
|
+
customEffect: (element, progress) => {
|
|
784
|
+
// Convert progress to angle (0-360 degrees)
|
|
785
|
+
const angle = Math.atan2(
|
|
786
|
+
progress.y - 0.5,
|
|
787
|
+
progress.x - 0.5
|
|
788
|
+
) * (180 / Math.PI);
|
|
789
|
+
|
|
790
|
+
element.style.transform = `rotate(${angle}deg)`;
|
|
791
|
+
},
|
|
792
|
+
centeredToTarget: true
|
|
793
|
+
}
|
|
794
|
+
]
|
|
795
|
+
}
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
**Example - Magnetic Effect with Distance Calculation**:
|
|
799
|
+
```typescript
|
|
800
|
+
{
|
|
801
|
+
key: 'magnetic-button',
|
|
802
|
+
trigger: 'pointerMove',
|
|
803
|
+
params: {
|
|
804
|
+
hitArea: 'self'
|
|
805
|
+
},
|
|
806
|
+
effects: [
|
|
807
|
+
{
|
|
808
|
+
customEffect: (element, progress) => {
|
|
809
|
+
// Calculate distance from center (0.5, 0.5)
|
|
810
|
+
const dx = (progress.x - 0.5) * 2; // -1 to 1
|
|
811
|
+
const dy = (progress.y - 0.5) * 2; // -1 to 1
|
|
812
|
+
|
|
813
|
+
// Apply magnetic pull effect
|
|
814
|
+
const maxMove = 20; // pixels
|
|
815
|
+
const moveX = dx * maxMove;
|
|
816
|
+
const moveY = dy * maxMove;
|
|
817
|
+
|
|
818
|
+
element.style.transform = `translate(${moveX}px, ${moveY}px)`;
|
|
819
|
+
},
|
|
820
|
+
centeredToTarget: true
|
|
821
|
+
}
|
|
822
|
+
]
|
|
823
|
+
}
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
**Example - Velocity-Based Motion Blur**:
|
|
827
|
+
```typescript
|
|
828
|
+
{
|
|
829
|
+
key: 'velocity-element',
|
|
830
|
+
trigger: 'pointerMove',
|
|
831
|
+
params: {
|
|
832
|
+
hitArea: 'root'
|
|
833
|
+
},
|
|
834
|
+
effects: [
|
|
835
|
+
{
|
|
836
|
+
customEffect: (element, progress) => {
|
|
837
|
+
// Use velocity for motion blur intensity
|
|
838
|
+
const velocity = progress.v || { x: 0, y: 0 };
|
|
839
|
+
const speed = Math.sqrt(velocity.x ** 2 + velocity.y ** 2);
|
|
840
|
+
|
|
841
|
+
// Apply blur based on speed
|
|
842
|
+
const blurAmount = Math.min(speed * 0.5, 10);
|
|
843
|
+
element.style.filter = `blur(${blurAmount}px)`;
|
|
844
|
+
|
|
845
|
+
// Move element towards mouse
|
|
846
|
+
const offsetX = (progress.x - 0.5) * 100;
|
|
847
|
+
const offsetY = (progress.y - 0.5) * 100;
|
|
848
|
+
element.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
|
|
849
|
+
},
|
|
850
|
+
centeredToTarget: false
|
|
851
|
+
}
|
|
852
|
+
]
|
|
853
|
+
}
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
**Example - Grid Cell Rotation Effect**:
|
|
857
|
+
```typescript
|
|
858
|
+
// First, cache grid cell positions for performance
|
|
859
|
+
const cellCache = new Map();
|
|
860
|
+
// Cache viewport size
|
|
861
|
+
const windowWidth = window.innerWidth;
|
|
862
|
+
const windowHeight = window.innerHeight;
|
|
863
|
+
// ... populate cache with cell center positions
|
|
864
|
+
// ... update `windowWidth/height` on window `resize` event
|
|
865
|
+
|
|
866
|
+
{
|
|
867
|
+
key: 'interactive-grid',
|
|
868
|
+
trigger: 'pointerMove',
|
|
869
|
+
params: {
|
|
870
|
+
hitArea: 'root'
|
|
871
|
+
},
|
|
872
|
+
effects: [
|
|
873
|
+
{
|
|
874
|
+
customEffect: (element, progress) => {
|
|
875
|
+
// Convert progress to viewport coordinates
|
|
876
|
+
const mouseX = progress.x * windowWidth;
|
|
877
|
+
const mouseY = progress.y * windowHeight;
|
|
878
|
+
|
|
879
|
+
// Iterate through cached grid cells
|
|
880
|
+
for (const [cell, cache] of cellCache) {
|
|
881
|
+
const deltaX = mouseX - cache.x;
|
|
882
|
+
const deltaY = mouseY - cache.y;
|
|
883
|
+
|
|
884
|
+
// Calculate angle pointing towards mouse
|
|
885
|
+
const angle = Math.atan2(deltaY, deltaX) * (180 / Math.PI) + 90;
|
|
886
|
+
|
|
887
|
+
// Calculate distance-based intensity
|
|
888
|
+
const dist = Math.sqrt(deltaX ** 2 + deltaY ** 2);
|
|
889
|
+
const intensity = Math.max(0, 1 - dist / 500);
|
|
890
|
+
|
|
891
|
+
cell.style.transform = `rotate(${angle}deg) scale(${1 + intensity * 0.2})`;
|
|
892
|
+
}
|
|
893
|
+
},
|
|
894
|
+
centeredToTarget: false
|
|
895
|
+
}
|
|
896
|
+
]
|
|
897
|
+
}
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
**Example - Active State Handling**:
|
|
901
|
+
```typescript
|
|
902
|
+
{
|
|
903
|
+
key: 'active-aware-element',
|
|
904
|
+
trigger: 'pointerMove',
|
|
905
|
+
params: {
|
|
906
|
+
hitArea: 'self'
|
|
907
|
+
},
|
|
908
|
+
effects: [
|
|
909
|
+
{
|
|
910
|
+
customEffect: (element, progress) => {
|
|
911
|
+
if (!progress.active) {
|
|
912
|
+
// Mouse left the hit area - reset or animate out
|
|
913
|
+
element.style.transform = 'scale(1)';
|
|
914
|
+
element.style.opacity = '0.7';
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
// Mouse is active in hit area
|
|
919
|
+
const scale = 1 + (1 - Math.abs(progress.x - 0.5) * 2) * 0.1;
|
|
920
|
+
element.style.transform = `scale(${scale})`;
|
|
921
|
+
element.style.opacity = '1';
|
|
922
|
+
},
|
|
923
|
+
centeredToTarget: true
|
|
924
|
+
}
|
|
925
|
+
]
|
|
926
|
+
}
|
|
927
|
+
```
|
|
928
|
+
|
|
929
|
+
### customEffect with Transition Smoothing
|
|
930
|
+
|
|
931
|
+
For smoother animations, you can use `transitionDuration` and `transitionEasing`:
|
|
932
|
+
|
|
933
|
+
```typescript
|
|
934
|
+
{
|
|
935
|
+
key: 'smooth-custom',
|
|
936
|
+
trigger: 'pointerMove',
|
|
937
|
+
params: {
|
|
938
|
+
hitArea: 'self'
|
|
939
|
+
},
|
|
940
|
+
effects: [
|
|
941
|
+
{
|
|
942
|
+
customEffect: (element, progress) => {
|
|
943
|
+
const x = (progress.x - 0.5) * 50;
|
|
944
|
+
const y = (progress.y - 0.5) * 50;
|
|
945
|
+
element.style.transform = `translate(${x}px, ${y}px)`;
|
|
946
|
+
},
|
|
947
|
+
transitionDuration: 100,
|
|
948
|
+
transitionEasing: 'easeOut',
|
|
949
|
+
centeredToTarget: true
|
|
950
|
+
}
|
|
951
|
+
]
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
---
|
|
956
|
+
|
|
957
|
+
## Rule 9: Multi-Element Custom Parallax with customEffect
|
|
958
|
+
|
|
959
|
+
**Use Case**: Complex parallax effects with custom physics or non-standard transformations across multiple layers.
|
|
960
|
+
|
|
961
|
+
**When to Apply**:
|
|
962
|
+
- For parallax with custom easing or physics
|
|
963
|
+
- When layers need different calculation methods
|
|
964
|
+
- For effects combining multiple CSS properties
|
|
965
|
+
|
|
966
|
+
**Pattern**:
|
|
967
|
+
```typescript
|
|
968
|
+
{
|
|
969
|
+
key: '[CONTAINER_KEY]',
|
|
970
|
+
trigger: 'pointerMove',
|
|
971
|
+
params: {
|
|
972
|
+
hitArea: '[HIT_AREA]'
|
|
973
|
+
},
|
|
974
|
+
effects: [
|
|
975
|
+
{
|
|
976
|
+
key: '[LAYER_1_KEY]',
|
|
977
|
+
customEffect: (element, progress) => {
|
|
978
|
+
[LAYER_1_CUSTOM_LOGIC]
|
|
979
|
+
},
|
|
980
|
+
centeredToTarget: true
|
|
981
|
+
},
|
|
982
|
+
{
|
|
983
|
+
key: '[LAYER_2_KEY]',
|
|
984
|
+
customEffect: (element, progress) => {
|
|
985
|
+
[LAYER_2_CUSTOM_LOGIC]
|
|
986
|
+
},
|
|
987
|
+
centeredToTarget: true
|
|
988
|
+
}
|
|
989
|
+
]
|
|
990
|
+
}
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
**Example - Depth-Based Custom Parallax**:
|
|
994
|
+
```typescript
|
|
995
|
+
{
|
|
996
|
+
key: 'parallax-scene',
|
|
997
|
+
trigger: 'pointerMove',
|
|
998
|
+
params: {
|
|
999
|
+
hitArea: 'self'
|
|
1000
|
+
},
|
|
1001
|
+
effects: [
|
|
1002
|
+
{
|
|
1003
|
+
key: 'bg-stars',
|
|
1004
|
+
customEffect: (element, progress) => {
|
|
1005
|
+
// Background: subtle movement, inverted direction
|
|
1006
|
+
const x = (0.5 - progress.x) * 10;
|
|
1007
|
+
const y = (0.5 - progress.y) * 10;
|
|
1008
|
+
element.style.transform = `translate(${x}px, ${y}px)`;
|
|
1009
|
+
},
|
|
1010
|
+
centeredToTarget: true
|
|
1011
|
+
},
|
|
1012
|
+
{
|
|
1013
|
+
key: 'mid-clouds',
|
|
1014
|
+
customEffect: (element, progress) => {
|
|
1015
|
+
// Midground: moderate movement with rotation
|
|
1016
|
+
const x = (progress.x - 0.5) * 30;
|
|
1017
|
+
const y = (progress.y - 0.5) * 20;
|
|
1018
|
+
const rotation = (progress.x - 0.5) * 5;
|
|
1019
|
+
element.style.transform = `translate(${x}px, ${y}px) rotate(${rotation}deg)`;
|
|
1020
|
+
},
|
|
1021
|
+
centeredToTarget: true
|
|
1022
|
+
},
|
|
1023
|
+
{
|
|
1024
|
+
key: 'fg-elements',
|
|
1025
|
+
customEffect: (element, progress) => {
|
|
1026
|
+
// Foreground: strong movement with scale
|
|
1027
|
+
const x = (progress.x - 0.5) * 60;
|
|
1028
|
+
const y = (progress.y - 0.5) * 40;
|
|
1029
|
+
const scale = 1 + Math.abs(progress.x - 0.5) * 0.1;
|
|
1030
|
+
element.style.transform = `translate(${x}px, ${y}px) scale(${scale})`;
|
|
1031
|
+
},
|
|
1032
|
+
centeredToTarget: true
|
|
1033
|
+
}
|
|
1034
|
+
]
|
|
1035
|
+
}
|
|
1036
|
+
```
|
|
1037
|
+
|
|
1038
|
+
---
|
|
1039
|
+
|
|
1040
|
+
## Advanced Patterns and Combinations
|
|
1041
|
+
|
|
1042
|
+
### Responsive Pointer Effects
|
|
1043
|
+
Adjusting pointer sensitivity based on device capabilities:
|
|
1044
|
+
|
|
1045
|
+
```typescript
|
|
1046
|
+
{
|
|
1047
|
+
key: 'responsive-element',
|
|
1048
|
+
trigger: 'pointerMove',
|
|
1049
|
+
conditions: ['supports-hover', 'desktop-only'],
|
|
1050
|
+
params: {
|
|
1051
|
+
hitArea: 'self'
|
|
1052
|
+
},
|
|
1053
|
+
effects: [
|
|
1054
|
+
{
|
|
1055
|
+
key: 'responsive-element',
|
|
1056
|
+
namedEffect: {
|
|
1057
|
+
type: 'Tilt3DMouse',
|
|
1058
|
+
angle: 20,
|
|
1059
|
+
perspective: 800,
|
|
1060
|
+
power: 'medium'
|
|
1061
|
+
},
|
|
1062
|
+
centeredToTarget: true
|
|
1063
|
+
}
|
|
1064
|
+
]
|
|
1065
|
+
},
|
|
1066
|
+
// Simplified version for touch devices
|
|
1067
|
+
{
|
|
1068
|
+
key: 'responsive-element',
|
|
1069
|
+
trigger: 'pointerMove',
|
|
1070
|
+
conditions: ['touch-device'],
|
|
1071
|
+
params: {
|
|
1072
|
+
hitArea: 'self'
|
|
1073
|
+
},
|
|
1074
|
+
effects: [
|
|
1075
|
+
{
|
|
1076
|
+
key: 'responsive-element',
|
|
1077
|
+
namedEffect: {
|
|
1078
|
+
type: 'ScaleMouse',
|
|
1079
|
+
scale: 1.02,
|
|
1080
|
+
power: 'soft'
|
|
1081
|
+
},
|
|
1082
|
+
centeredToTarget: true
|
|
1083
|
+
}
|
|
1084
|
+
]
|
|
1085
|
+
}
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
### Contextual Hit Areas
|
|
1089
|
+
Different hit areas for different interaction contexts:
|
|
1090
|
+
|
|
1091
|
+
```typescript
|
|
1092
|
+
// Local interaction - mouse must be over element
|
|
1093
|
+
{
|
|
1094
|
+
key: 'local-card',
|
|
1095
|
+
trigger: 'pointerMove',
|
|
1096
|
+
params: {
|
|
1097
|
+
hitArea: 'self'
|
|
1098
|
+
},
|
|
1099
|
+
effects: [
|
|
1100
|
+
{
|
|
1101
|
+
key: 'local-card',
|
|
1102
|
+
namedEffect: {
|
|
1103
|
+
type: 'Tilt3DMouse',
|
|
1104
|
+
angle: 15,
|
|
1105
|
+
power: 'medium'
|
|
1106
|
+
},
|
|
1107
|
+
centeredToTarget: true
|
|
1108
|
+
}
|
|
1109
|
+
]
|
|
1110
|
+
},
|
|
1111
|
+
// Global interaction - responds to mouse anywhere
|
|
1112
|
+
{
|
|
1113
|
+
key: 'global-background',
|
|
1114
|
+
trigger: 'pointerMove',
|
|
1115
|
+
params: {
|
|
1116
|
+
hitArea: 'root'
|
|
1117
|
+
},
|
|
1118
|
+
effects: [
|
|
1119
|
+
{
|
|
1120
|
+
key: 'ambient-element',
|
|
1121
|
+
namedEffect: {
|
|
1122
|
+
type: 'AiryMouse',
|
|
1123
|
+
distance: { value: 30, type: 'px' },
|
|
1124
|
+
power: 'soft'
|
|
1125
|
+
},
|
|
1126
|
+
centeredToTarget: false
|
|
1127
|
+
}
|
|
1128
|
+
]
|
|
1129
|
+
}
|
|
1130
|
+
```
|
|
1131
|
+
|
|
1132
|
+
### Axis-Constrained Effects
|
|
1133
|
+
Controlling movement direction for specific design needs:
|
|
1134
|
+
|
|
1135
|
+
```typescript
|
|
1136
|
+
{
|
|
1137
|
+
key: 'constrained-container',
|
|
1138
|
+
trigger: 'pointerMove',
|
|
1139
|
+
params: {
|
|
1140
|
+
hitArea: 'self'
|
|
1141
|
+
},
|
|
1142
|
+
effects: [
|
|
1143
|
+
{
|
|
1144
|
+
key: 'horizontal-slider',
|
|
1145
|
+
namedEffect: {
|
|
1146
|
+
type: 'TrackMouse',
|
|
1147
|
+
distance: { value: 100, type: 'px' },
|
|
1148
|
+
axis: 'horizontal',
|
|
1149
|
+
power: 'medium'
|
|
1150
|
+
},
|
|
1151
|
+
centeredToTarget: true
|
|
1152
|
+
},
|
|
1153
|
+
{
|
|
1154
|
+
key: 'vertical-indicator',
|
|
1155
|
+
namedEffect: {
|
|
1156
|
+
type: 'ScaleMouse',
|
|
1157
|
+
scale: 1.2,
|
|
1158
|
+
distance: { value: 150, type: 'px' },
|
|
1159
|
+
axis: 'vertical',
|
|
1160
|
+
power: 'medium'
|
|
1161
|
+
},
|
|
1162
|
+
centeredToTarget: true
|
|
1163
|
+
}
|
|
1164
|
+
]
|
|
1165
|
+
}
|
|
1166
|
+
```
|
|
1167
|
+
|
|
1168
|
+
---
|
|
1169
|
+
|
|
1170
|
+
## Best Practices for PointerMove Interactions
|
|
1171
|
+
|
|
1172
|
+
### Effect Type Selection Guidelines
|
|
1173
|
+
|
|
1174
|
+
**When to use `namedEffect` (Preferred)**:
|
|
1175
|
+
1. For standard mouse-tracking effects (tilt, track, scale, blur)
|
|
1176
|
+
2. When GPU-optimized performance is critical
|
|
1177
|
+
3. For effects that match preset behavior (3D tilt, elastic following)
|
|
1178
|
+
4. When you don't need custom physics or calculations
|
|
1179
|
+
|
|
1180
|
+
**When to use `customEffect`**:
|
|
1181
|
+
1. For custom physics-based animations (springs, gravity)
|
|
1182
|
+
2. When you need access to velocity data (`progress.v`)
|
|
1183
|
+
3. For complex DOM manipulations (updating multiple elements)
|
|
1184
|
+
4. When creating effects not covered by named presets
|
|
1185
|
+
5. For grid/particle systems with many elements
|
|
1186
|
+
6. For controlling WebGL/WebGPU effects
|
|
1187
|
+
|
|
1188
|
+
**Never use `keyframeEffect`** with `pointerMove` - pointer progress is 2D and cannot map to linear keyframes.
|
|
1189
|
+
|
|
1190
|
+
### Performance Guidelines
|
|
1191
|
+
1. **Use hardware-accelerated properties** - prefer transforms over position changes
|
|
1192
|
+
2. **Limit simultaneous pointer effects** - too many can cause performance issues
|
|
1193
|
+
3. **Test on various devices** - pointer sensitivity varies across hardware
|
|
1194
|
+
4. **Cache DOM queries in customEffect** - avoid repeated `querySelector` calls
|
|
1195
|
+
5. **Use `requestAnimationFrame` sparingly** - the library already handles frame timing
|
|
1196
|
+
6. **Prefer `namedEffect` over `customEffect`** - named effects are optimized for GPU acceleration
|
|
1197
|
+
|
|
1198
|
+
### Hit Area Guidelines
|
|
1199
|
+
1. **Use `hitArea: 'self'`** for local element interactions (cards, buttons, hover effects)
|
|
1200
|
+
2. **Use `hitArea: 'root'`** for global cursor followers and ambient effects
|
|
1201
|
+
3. **Consider container boundaries** when choosing hit areas
|
|
1202
|
+
4. **Test hit area responsiveness** across different screen sizes
|
|
1203
|
+
5. **`'self'`** is more performant than `'root'` - use when possible
|
|
1204
|
+
|
|
1205
|
+
### Centering Guidelines
|
|
1206
|
+
1. **Set `centeredToTarget: true`** when target differs from source (e.g., animating child element from parent)
|
|
1207
|
+
2. **Use `centeredToTarget: false`** for cursor followers and global effects
|
|
1208
|
+
3. **Test centering behavior** with different element sizes
|
|
1209
|
+
4. **Consider responsive design** when setting centering
|
|
1210
|
+
5. **Centering affects how progress.x/y map to element position**
|
|
1211
|
+
|
|
1212
|
+
### User Experience Guidelines
|
|
1213
|
+
1. **Keep pointer effects subtle** to avoid overwhelming users
|
|
1214
|
+
2. **Ensure effects enhance rather than distract** from content
|
|
1215
|
+
3. **Provide visual feedback** that feels natural and responsive
|
|
1216
|
+
4. **Test with actual users** to validate interaction quality
|
|
1217
|
+
|
|
1218
|
+
### Accessibility Considerations
|
|
1219
|
+
1. **Respect `prefers-reduced-motion`** for all pointer animations
|
|
1220
|
+
2. **Ensure touch device compatibility** with appropriate alternatives
|
|
1221
|
+
3. **Don't rely solely on pointer effects** for important interactions
|
|
1222
|
+
4. **Provide keyboard alternatives** for interactive elements
|
|
1223
|
+
|
|
1224
|
+
### Common Use Cases by Pattern
|
|
1225
|
+
|
|
1226
|
+
**Single Element 3D Effects (Rule 1)** - `namedEffect`:
|
|
1227
|
+
- Interactive product cards
|
|
1228
|
+
- 3D showcase elements
|
|
1229
|
+
- Immersive button interactions
|
|
1230
|
+
- Portfolio item presentations
|
|
1231
|
+
|
|
1232
|
+
**Movement Followers (Rule 2)** - `namedEffect`:
|
|
1233
|
+
- Cursor follower elements
|
|
1234
|
+
- Floating decorative elements
|
|
1235
|
+
- Responsive UI indicators
|
|
1236
|
+
- Interactive overlays
|
|
1237
|
+
|
|
1238
|
+
**Scale & Deformation (Rule 3)** - `namedEffect`:
|
|
1239
|
+
- Organic interface elements
|
|
1240
|
+
- Interactive morphing shapes
|
|
1241
|
+
- Creative scaling buttons
|
|
1242
|
+
- Blob-like interactions
|
|
1243
|
+
|
|
1244
|
+
**Visual Effects (Rule 4)** - `namedEffect`:
|
|
1245
|
+
- Creative interface elements
|
|
1246
|
+
- Motion blur interactions
|
|
1247
|
+
- Spinning decorative elements
|
|
1248
|
+
- Dynamic visual feedback
|
|
1249
|
+
|
|
1250
|
+
**Multi-Element Parallax (Rule 5)** - `namedEffect`:
|
|
1251
|
+
- Layered background effects
|
|
1252
|
+
- Depth-based interactions
|
|
1253
|
+
- Immersive hero sections
|
|
1254
|
+
- Complex scene responses
|
|
1255
|
+
|
|
1256
|
+
**Group Coordination (Rule 6)** - `namedEffect`:
|
|
1257
|
+
- Interactive card grids
|
|
1258
|
+
- Navigation menu systems
|
|
1259
|
+
- Gallery hover effects
|
|
1260
|
+
- Coordinated UI responses
|
|
1261
|
+
|
|
1262
|
+
**Global Followers (Rule 7)** - `namedEffect`:
|
|
1263
|
+
- Custom cursor implementations
|
|
1264
|
+
- Page-wide decorative elements
|
|
1265
|
+
- Global interactive overlays
|
|
1266
|
+
- Immersive cursor experiences
|
|
1267
|
+
|
|
1268
|
+
**Custom Pointer Effects (Rule 8)** - `customEffect`:
|
|
1269
|
+
- Grid-based rotation systems
|
|
1270
|
+
- Magnetic pull/push effects
|
|
1271
|
+
- Physics-based animations
|
|
1272
|
+
- Velocity-reactive effects
|
|
1273
|
+
- Complex DOM manipulations
|
|
1274
|
+
- Particle systems
|
|
1275
|
+
|
|
1276
|
+
**Multi-Element Custom Parallax (Rule 9)** - `customEffect`:
|
|
1277
|
+
- Non-linear parallax physics
|
|
1278
|
+
- Layers with different calculation methods
|
|
1279
|
+
- Combined transform effects per layer
|
|
1280
|
+
- Custom easing per element
|
|
1281
|
+
|
|
1282
|
+
### Troubleshooting Common Issues
|
|
1283
|
+
|
|
1284
|
+
**Poor pointer responsiveness**:
|
|
1285
|
+
- Check `power` settings (soft/medium/hard) for namedEffect
|
|
1286
|
+
- Verify `hitArea` configuration
|
|
1287
|
+
- Test `centeredToTarget` settings
|
|
1288
|
+
- Ensure target elements are properly positioned
|
|
1289
|
+
|
|
1290
|
+
**Performance issues**:
|
|
1291
|
+
- Reduce number of simultaneous effects
|
|
1292
|
+
- Use simpler named effects
|
|
1293
|
+
- Check for CSS conflicts
|
|
1294
|
+
- Test on lower-end devices
|
|
1295
|
+
- In customEffect: cache DOM queries outside the callback
|
|
1296
|
+
- Avoid creating objects inside customEffect callbacks
|
|
1297
|
+
|
|
1298
|
+
**customEffect not updating smoothly**:
|
|
1299
|
+
- Add `transitionDuration` and `transitionEasing` for smoother transitions
|
|
1300
|
+
- Ensure style changes use transform/opacity for GPU acceleration
|
|
1301
|
+
- Avoid expensive calculations inside the callback
|
|
1302
|
+
- Consider debouncing complex logic
|
|
1303
|
+
|
|
1304
|
+
**customEffect progress values unexpected**:
|
|
1305
|
+
- Remember x/y are 0-1 normalized (not pixel values)
|
|
1306
|
+
- Check `centeredToTarget` setting affects coordinate mapping
|
|
1307
|
+
- Verify `hitArea` matches expected tracking area
|
|
1308
|
+
- Use `progress.active` to handle edge cases
|
|
1309
|
+
|
|
1310
|
+
**Unexpected behavior on touch devices**:
|
|
1311
|
+
- Implement appropriate conditions for touch vs. mouse
|
|
1312
|
+
- Provide touch-friendly alternatives
|
|
1313
|
+
- Test pointer events on mobile devices
|
|
1314
|
+
- Consider disabling complex effects on touch
|
|
1315
|
+
|
|
1316
|
+
**Effects not triggering**:
|
|
1317
|
+
- Verify source element exists and is visible
|
|
1318
|
+
- Check `data-interact-key` matches CSS selector
|
|
1319
|
+
- Ensure proper hit area configuration
|
|
1320
|
+
- Test mouse event propagation
|
|
1321
|
+
|
|
1322
|
+
**keyframeEffect not working with pointerMove**:
|
|
1323
|
+
- This is expected! `keyframeEffect` requires linear 0-1 progress
|
|
1324
|
+
- `pointerMove` provides 2D progress (x, y object)
|
|
1325
|
+
- Use `namedEffect` or `customEffect` instead
|
|
1326
|
+
|
|
1327
|
+
---
|
|
1328
|
+
|
|
1329
|
+
## Quick Reference: Effect Type Selection
|
|
1330
|
+
|
|
1331
|
+
| Requirement | Use This | Why |
|
|
1332
|
+
|-------------|----------|-----|
|
|
1333
|
+
| Standard 3D tilt | `namedEffect: { type: 'Tilt3DMouse' }` | GPU-optimized, battle-tested |
|
|
1334
|
+
| Cursor following | `namedEffect: { type: 'TrackMouse' }` | Built-in physics |
|
|
1335
|
+
| Custom physics | `customEffect` | Full control over calculations |
|
|
1336
|
+
| Velocity-based effects | `customEffect` | Access to `progress.v` |
|
|
1337
|
+
| Grid/particle systems | `customEffect` | Can manipulate many elements |
|
|
1338
|
+
|
|
1339
|
+
---
|
|
1340
|
+
|
|
1341
|
+
These rules provide comprehensive coverage for PointerMove trigger interactions in `@wix/interact`, supporting all hit area configurations, centering options, named effect types, and custom effect patterns as outlined in the development plan Stage 1.5.
|