@webgazer-ts/react
v0.2.0
Published
React hooks and components for Webgazer.ts eye tracking library
Maintainers
Readme
@webgazer-ts/react
React hooks and components for Webgazer.ts eye tracking library.
Features
✨ 7 Powerful Hooks:
useWebgazer()- Complete eye tracking controluseGazeTracking()- Simple gaze data accessuseCalibration()- Programmatic calibrationuseGazeElement()- Track gaze on elementsuseGazeHeatmap()- Heatmap visualizationuseGazeRecording()- Session recordinguseWebgazerContext()- Context access
🎨 4 Ready-to-Use Components:
<WebgazerProvider>- Context provider<CalibrationScreen>- Full-screen calibration UI<GazeElement>- Gaze-aware wrapper<HeatmapOverlay>- Heatmap visualization
🔧 Developer Experience:
- Full TypeScript support
- Automatic lifecycle management
- Zero configuration needed
- Comprehensive examples
Installation
npm install @webgazer-ts/react
# or
pnpm add @webgazer-ts/react
# or
yarn add @webgazer-ts/reactQuick Start
Basic Usage
import { useWebgazer } from '@webgazer-ts/react';
function App() {
const { gazeData, start, stop, isRunning } = useWebgazer({
autoStart: true,
});
return (
<div>
<h1>Gaze Tracker</h1>
<div>
Status: {isRunning ? '🟢 Running' : '🔴 Stopped'}
</div>
{gazeData && (
<div>
Looking at: ({Math.round(gazeData.x)}, {Math.round(gazeData.y)})
</div>
)}
<button onClick={start}>Start</button>
<button onClick={stop}>Stop</button>
</div>
);
}With Provider Pattern
import { WebgazerProvider, useGazeTracking } from '@webgazer-ts/react';
function GazeDisplay() {
const gaze = useGazeTracking();
return gaze ? (
<div>Gaze: ({gaze.x}, {gaze.y})</div>
) : (
<div>Waiting for gaze data...</div>
);
}
function App() {
return (
<WebgazerProvider
autoStart={true}
showVideoPreview={true}
>
<GazeDisplay />
</WebgazerProvider>
);
}API Reference
Hooks
useWebgazer(options?)
Main hook for initializing and controlling Webgazer.
Options:
autoStart?: boolean- Start tracking automatically (default: false)tracker?: 'TFFacemesh'- Face tracker to useregression?: 'ridge' | 'ridgeThreaded' | 'ridgeWeighted'- Regression modelsaveDataAcrossSessions?: boolean- Save calibration data (default: true)showVideoPreview?: boolean- Show video preview (default: false)showFaceOverlay?: boolean- Show face mesh overlay (default: false)showGazeDot?: boolean- Show gaze prediction dot (default: false)applyKalmanFilter?: boolean- Use Kalman filter (default: true)onGaze?: (data, timestamp) => void- Callback for gaze updates
Returns:
gazeData: GazePrediction | null- Current gaze positionisRunning: boolean- Whether tracking is activecalibrationCount: number- Number of calibration pointsstart: () => Promise<void>- Start trackingstop: () => Promise<void>- Stop trackingpause: () => Promise<void>- Pause trackingresume: () => Promise<void>- Resume trackingclearData: () => void- Clear calibration datashowVideo: () => void- Show video previewhideVideo: () => void- Hide video preview
useGazeTracking()
Simplified hook that returns current gaze data. Must be used within WebgazerProvider.
Returns:
GazePrediction | null- Current gaze position
useCalibration(options?)
Programmatic control over calibration process.
Options:
pointCount?: number- Number of calibration points (default: 9)pointDuration?: number- Duration per point in ms (default: 1000)autoAdvance?: boolean- Auto-advance to next point (default: true)onComplete?: (result) => void- Callback when calibration completesonPointComplete?: (index) => void- Callback after each point
Returns:
isCalibrating: boolean- Is calibration activeprogress: number- Progress percentage (0-100)currentPoint: CalibrationPoint | null- Current point { x, y, index }startCalibration: () => void- Start calibrationstopCalibration: () => void- Stop calibrationnextPoint: () => void- Advance to next point
Example:
const { isCalibrating, currentPoint, startCalibration } = useCalibration({
pointCount: 9,
autoAdvance: true,
onComplete: (result) => console.log('Done!', result),
});useGazeElement(options?)
Track when user is looking at a specific element.
Options:
threshold?: number- Hit detection tolerance in pixels (default: 50)minDwellTime?: number- Min dwell time for callback in ms (default: 0)onEnter?: () => void- Called when gaze enters elementonLeave?: () => void- Called when gaze leaves elementonDwell?: () => void- Called after minDwellTime
Returns:
ref: RefObject<HTMLElement>- Ref to attach to elementisLooking: boolean- Is user currently looking at elementdwellTime: number- Time user has been looking in ms
Example:
const { ref, isLooking, dwellTime } = useGazeElement({
threshold: 50,
minDwellTime: 2000,
onDwell: () => console.log('User dwelled for 2s!'),
});
<button ref={ref} style={{ opacity: isLooking ? 1 : 0.5 }}>
Look at me! {dwellTime > 0 && `(${(dwellTime/1000).toFixed(1)}s)`}
</button>useGazeHeatmap(options?)
Generate and visualize gaze heatmap data.
Options:
width?: number- Canvas width (default: window.innerWidth)height?: number- Canvas height (default: window.innerHeight)radius?: number- Point radius (default: 30)maxOpacity?: number- Max opacity (default: 0.8)blur?: number- Blur amount (default: 15)gradient?: Record<number, string>- Color gradient
Returns:
canvasRef: RefObject<HTMLCanvasElement>- Ref for canvas elementpoints: HeatmapPoint[]- Array of gaze pointsclear: () => void- Clear heatmapexportData: () => string- Export as CSV stringexportImage: () => string | null- Export as PNG data URL
Example:
const { canvasRef, points, clear, exportData } = useGazeHeatmap({
radius: 30,
maxOpacity: 0.8,
});
<>
<canvas ref={canvasRef} style={{ position: 'fixed', top: 0, left: 0 }} />
<button onClick={clear}>Clear ({points.length})</button>
</>useGazeRecording()
Record gaze sessions for analysis.
Returns:
isRecording: boolean- Is recording activedata: GazeRecordingEntry[]- Array of recorded pointsstartRecording: () => void- Start recordingstopRecording: () => void- Stop recordingclearData: () => void- Clear recorded dataexportCSV: () => void- Export and download as CSVexportJSON: () => void- Export and download as JSON
Example:
const { isRecording, data, startRecording, stopRecording, exportCSV } = useGazeRecording();
<>
<button onClick={isRecording ? stopRecording : startRecording}>
{isRecording ? 'Stop' : 'Start'} Recording
</button>
<p>Recorded: {data.length} points</p>
<button onClick={exportCSV}>Export CSV</button>
</>Components
<WebgazerProvider>
Context provider for Webgazer. Accepts all useWebgazer options as props.
<WebgazerProvider autoStart={true}>
{/* Your components */}
</WebgazerProvider><CalibrationScreen>
Full-screen calibration UI with animated points.
Props:
pointCount?: number- Number of points (default: 9)pointDuration?: number- Duration per point (default: 1000)autoAdvance?: boolean- Auto-advance (default: true)onComplete?: (result) => void- Completion callbackonCancel?: () => void- Cancel callbacktheme?: object- Customize colors
Example:
<CalibrationScreen
pointCount={9}
onComplete={(result) => {
if (result.success) {
console.log('Calibration complete!');
}
}}
theme={{
backgroundColor: 'rgba(0, 0, 0, 0.95)',
pointColor: '#ff0000',
progressColor: '#00ff00',
}}
/><GazeElement>
Wrapper component that responds to gaze.
Props:
- All
useGazeElementoptions children: ReactNode- Content to wrapclassName?: string- CSS classstyle?: CSSProperties- Base stylelookingStyle?: CSSProperties- Style when lookingonDwellStyle?: CSSProperties- Style when dwelling
Example:
<GazeElement
minDwellTime={2000}
onDwell={() => console.log('Dwelled!')}
style={{ padding: '20px', background: 'gray' }}
lookingStyle={{ background: 'lightblue', transform: 'scale(1.1)' }}
onDwellStyle={{ background: 'yellow' }}
>
<h3>Interactive Card</h3>
<p>Look at me to interact!</p>
</GazeElement><HeatmapOverlay>
Visual overlay showing gaze heatmap.
Props:
- All
useGazeHeatmapoptions showControls?: boolean- Show control buttons (default: false)onClear?: () => void- Clear callbackstyle?: CSSProperties- Canvas style
Example:
<HeatmapOverlay
radius={30}
showControls={true}
onClear={() => console.log('Heatmap cleared')}
/>Complete Examples
Example 1: Full Calibration Flow
import { useState } from 'react';
import { CalibrationScreen, useWebgazer } from '@webgazer-ts/react';
function App() {
const [needsCalibration, setNeedsCalibration] = useState(true);
const { calibrationCount } = useWebgazer({ autoStart: true });
if (needsCalibration && calibrationCount < 9) {
return (
<CalibrationScreen
pointCount={9}
onComplete={() => setNeedsCalibration(false)}
/>
);
}
return <div>Main App Content</div>;
}Example 2: Gaze-Aware Dashboard
import { WebgazerProvider, GazeElement } from '@webgazer-ts/react';
function Dashboard() {
return (
<WebgazerProvider autoStart>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}>
<GazeElement
minDwellTime={2000}
onDwell={() => console.log('User interested in sales')}
lookingStyle={{ transform: 'scale(1.05)' }}
>
<Card title="Sales" value="$1.2M" />
</GazeElement>
<GazeElement
minDwellTime={2000}
onDwell={() => console.log('User checking users')}
lookingStyle={{ transform: 'scale(1.05)' }}
>
<Card title="Users" value="10.5K" />
</GazeElement>
</div>
</WebgazerProvider>
);
}Example 3: Heatmap Analysis
import { WebgazerProvider, HeatmapOverlay } from '@webgazer-ts/react';
function App() {
return (
<WebgazerProvider autoStart>
<HeatmapOverlay
showControls
radius={40}
gradient={{
0.0: 'blue',
0.5: 'lime',
1.0: 'red',
}}
/>
<YourContent />
</WebgazerProvider>
);
}Example 4: Session Recording
import { useWebgazer, useGazeRecording } from '@webgazer-ts/react';
function RecordingApp() {
const { isRunning } = useWebgazer({ autoStart: true });
const { isRecording, data, startRecording, stopRecording, exportCSV } = useGazeRecording();
return (
<div>
<p>Status: {isRunning ? 'Tracking' : 'Not running'}</p>
<button onClick={isRecording ? stopRecording : startRecording}>
{isRecording ? '⏹️ Stop' : '🔴 Start'} Recording
</button>
<p>Recorded: {data.length} points</p>
<button onClick={exportCSV} disabled={data.length === 0}>
Export CSV
</button>
</div>
);
}TypeScript
Fully typed with TypeScript. All types are exported:
import type {
GazePrediction,
WebgazerConfig,
UseWebgazerOptions,
UseWebgazerReturn,
UseCalibrationOptions,
CalibrationResult,
UseGazeElementOptions,
UseGazeElementReturn,
HeatmapPoint,
UseGazeHeatmapOptions,
GazeRecordingEntry,
} from '@webgazer-ts/react';License
GPL-3.0-or-later
Credits
Based on Webgazer.js by Brown HCI.
