
Syncfusion React Circular Gauge
- 387 installs
- 3 repo stars
- Updated July 28, 2026
- syncfusion/react-ui-components-skills
Use syncfusion-react-circular-gauge for development tasks
About
syncfusion-react-circular-gauge: A skill for development. This provides functionality for development workflows.
- syncfusion-react-circular-gauge
Syncfusion React Circular Gauge by the numbers
- 387 all-time installs (skills.sh)
- +52 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,118 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/syncfusion/react-ui-components-skills --skill syncfusion-react-circular-gaugeAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 387 |
|---|---|
| repo stars | ★ 3 |
| Last updated | July 28, 2026 |
| Repository | syncfusion/react-ui-components-skills ↗ |
What it does
Use syncfusion-react-circular-gauge for development tasks
Files
Implementing Syncfusion React Circular Gauge
When to Use This Skill
Use the Circular Gauge component when you need to:
- Display measurements on a circular scale (speedometers, temperature gauges, fuel indicators)
- Monitor KPIs and metrics in dashboards (business metrics, sensor readings)
- Visualize progress or percentages in a circular format
- Show real-time data with animated pointer updates
- Create responsive data visualizations with multiple pointers and ranges
- Print or export gauge visualizations for reports
The Circular Gauge is ideal for applications requiring visual representation of values on a circular scale with customizable appearance, animations, and interactivity.
---
Component Overview
Syncfusion React Circular Gauge (@syncfusion/ej2-react-circulargauge) is a data visualization component that displays values on a circular scale. It consists of:
- Axes - The circular scale tracks with customizable angles, direction, and styling
- Pointers - Value indicators in three types: Needle (default), RangeBar, or Marker
- Ranges - Colored segments representing value ranges (e.g., 0-25%, 25-50%)
- Annotations - Text or image overlays for labels and callouts
- Legend - Optional legend displaying range meanings
- Export - Print, PDF, PNG, or SVG export capabilities
---
Documentation and Navigation Guide
Choose the reference based on what you need to implement:
Getting Started & Setup
📄 Read: references/getting-started.md
- Install
@syncfusion/ej2-react-circulargaugepackage - Setup in Vite or Create React App
- Basic component initialization
- Minimal working example
- CSS imports and themes
- When to read: First time setup or new project integration
Gauge Structure: Axes, Pointers & Ranges
📄 Read: references/axes-pointers-ranges.md
- Configure axes (angles, direction, styling)
- Add and customize pointers (Needle, RangeBar, Marker types)
- Define ranges with colors and labels
- Multiple axes and pointers
- When to read: Building the core gauge structure and data visualization
Visual Appearance & Dimensions
📄 Read: references/appearance-dimensions.md
- Add titles and customize styling
- Position gauge (centerX, centerY)
- Set dimensions (width, height, margin)
- Apply backgrounds, borders, color schemes
- Responsive design
- When to read: Customizing gauge look, sizing, and layout
Annotations & Legend
📄 Read: references/annotations-legend.md
- Add text annotations
- Add image annotations
- Position annotations
- Display and customize legend
- Handle legend interactions
- When to read: Adding labels, callouts, or explanatory elements
Advanced Features
📄 Read: references/advanced-features.md
- Animation effects and timing
- User interaction (events, tooltips)
- Print and export to PDF/PNG/SVG
- Real-time data binding
- Multiple gauge instances
- When to read: Adding interactions, animations, or export functionality
API Reference
📄 Read: references/api-reference.md
- Component props, events, methods, and child directive reference
- Quick lookup for commonly used props, methods and event args
- When to read: When you need exact API names, types or method signatures
Accessibility & Internationalization
📄 Read: references/accessibility-i18n.md
- WCAG 2.1 compliance and ARIA support
- Screen reader compatibility
- Keyboard navigation
- RTL language support
- Localization and culture settings
- When to read: Making gauges accessible or supporting multiple languages
Common Patterns & Use Cases
📄 Read: references/common-patterns.md
- Speedometer pattern
- Progress/percentage gauge pattern
- Temperature/sensor monitoring
- Multi-pointer dashboards
- Real-time updates with animations
- Performance tips and troubleshooting
- When to read: Looking for common implementations or solving issues
---
Quick Start Example
Here's a minimal working example to get started:
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective, RangesDirective, RangeDirective }
from '@syncfusion/ej2-react-circulargauge';
export function App() {
return (
<div style={{ height: '500px' }}>
<CircularGaugeComponent
title="Speedometer"
centerX="50%"
centerY="50%"
>
<AxesDirective>
<AxisDirective
startAngle={270}
endAngle={90}
minimum={0}
maximum={100}
>
<RangesDirective>
<RangeDirective start={0} end={30} color='#1E7145' />
<RangeDirective start={30} end={60} color='#F7D900' />
<RangeDirective start={60} end={100} color='#C1192B' />
</RangesDirective>
<PointersDirective>
<PointerDirective
value={65}
type='Needle'
radius='70%'
/>
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}Install the package first:
npm install @syncfusion/ej2-react-circulargauge --save---
Common Patterns
Pattern 1: Simple Progress Indicator
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<RangesDirective>
<RangeDirective start={0} end={50} color='#E8E8E8' />
<RangeDirective start={50} end={100} color='#4CAF50' />
</RangesDirective>
<PointersDirective>
<PointerDirective value={75} type='RangeBar' />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>Pattern 2: Multi-Pointer Dashboard
Use multiple pointers on the same axis to compare values:
<PointersDirective>
<PointerDirective value={45} type='Needle' />
<PointerDirective value={60} type='Marker' />
</PointersDirective>Pattern 3: Real-Time Updates
const [value, setValue] = useState(50);
// Update pointer value on interval
useEffect(() => {
const timer = setInterval(() => {
setValue(prev => (prev + Math.random() * 10) % 100);
}, 1000);
return () => clearInterval(timer);
}, []);
// Bind value to pointer
<PointerDirective value={value} />---
Key Configuration Props
| Prop | Type | Purpose |
|---|---|---|
title | string | Gauge title displayed at top |
centerX / centerY | string | Position (% or px) |
startAngle / endAngle | number | Axis sweep degrees (0-360) |
minimum / maximum | number | Axis scale range |
value (pointer) | number | Current pointer value |
type (pointer) | 'Needle' \ | 'RangeBar' \ |
radius (pointer) | string | Pointer length (% or px) |
color | string | Element color (hex, rgb, name) |
direction | 'ClockWise' \ | 'AntiClockWise' |
animationDuration | number | Animation time in milliseconds |
---
For the complete API listing (all component props, events, methods and child directives) see: references/api-reference.md
Common Use Cases
1. Speedometer/Speed Monitor - Display vehicle speed with colored ranges 2. Temperature Gauge - Monitor temperature with hot/cold indicators 3. Performance KPI - Show system metrics or business KPIs 4. Fuel/Battery Level - Visualize resource consumption 5. Network Traffic - Display bandwidth usage in real-time 6. Sports/Gaming Scores - Show player stats or game progress 7. Industrial Monitoring - Sensor data visualization 8. Percentage/Progress - Alternative circular progress visualization
---
Next Steps
1. Start with Getting Started to set up your first gauge 2. Build structure using Axes, Pointers & Ranges reference 3. Customize appearance with styling reference 4. Add interactions with Advanced Features reference 5. Test accessibility using Accessibility reference 6. Reference common patterns for implementation ideas
For more details or advanced scenarios, consult the specific reference files linked above.
Accessibility & Internationalization
Table of contents
- WCAG 2.1 Compliance
- ARIA Support
- ARIA Live Regions
- Tab Navigation
- Keyboard Navigation
- Enable Keyboard Support
- Keyboard Shortcuts
- Screen Reader Support
- Semantic HTML
- Accessible Annotations
- Text Alternatives
- Color Contrast
- Sufficient Contrast Ratios
- High Contrast Theme
- Focus Indicators
- RTL (Right-to-Left) Support
- Enable RTL
- RTL Example with Arabic
- Internationalization (i18n)
- Locale Settings
- Number Formatting
- Currency Formatting
- Date/Time Culture
- Multi-Language Example
- Accessibility Checklist
- Tips and Best Practices
See the API quick reference: api-reference.md for prop names, event args and methods.
WCAG 2.1 Compliance
ARIA Support
Add accessible labels and descriptions:
import * as React from "react";
import { createRoot } from 'react-dom/client';
import { CircularGaugeComponent, AxesDirective, AxisDirective, PointersDirective, PointerDirective } from '@syncfusion/ej2-react-circulargauge';
export function App() {
return(
<CircularGaugeComponent
aria-label="Speed Gauge"
description="A speedometer gauge showing vehicle speed from 0 to 240 km/h"
>
<AxesDirective>
<AxisDirective
aria-label="Speed Gauge"
>
<PointersDirective>
<PointerDirective
aria-label="Current Speed: 85 km/h"
value={85}
/>
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);ARIA Live Regions
Announce value changes to screen readers:
<div aria-live="polite" aria-atomic="true">
<span>Current speed: {currentValue} km/h</span>
</div>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>Tab Navigation
Ensure keyboard navigation works:
<div tabIndex={0} role="group" aria-label="Performance Metrics">
<CircularGaugeComponent
tabIndex={0}
aria-label="Performance Gauge"
>
{/* gauge content */}
</CircularGaugeComponent>
</div>---
Screen Reader Support
Semantic HTML
Wrap gauge with proper landmarks:
<section aria-label="Performance Dashboard">
<h2>System Performance Metrics</h2>
<article aria-label="CPU Usage Gauge">
<CircularGaugeComponent
aria-label="CPU usage gauge"
role="img"
aria-describedby="cpu-description"
>
{/* gauge content */}
</CircularGaugeComponent>
<p id="cpu-description">
Shows current CPU usage percentage. Green indicates optimal (0-30%), yellow indicates normal (30-60%), red indicates high usage (60-100%).
</p>
</article>
</section>Accessible Annotations
<AnnotationDirective
content="75% - Above Normal"
textStyle={{ size: '14px' }}
role="status"
aria-label="Current CPU usage is 75 percent, above normal"
/>Text Alternatives
Provide text descriptions for visual elements:
<div>
<div style={{ height: '400px' }}>
<CircularGaugeComponent
aria-label="CPU Usage Gauge"
role="img"
>
{/* gauge */}
</CircularGaugeComponent>
</div>
<div role="status" aria-live="polite">
<p>CPU Usage: {value}%</p>
{value > 80 && <p>Warning: High CPU usage detected.</p>}
</div>
</div>---
Color Contrast
Sufficient Contrast Ratios
Ensure text and elements meet WCAG AA standards (4.5:1 for normal text):
// ✅ Good contrast
import { CircularGaugeComponent, AxesDirective, AxisDirective, RangesDirective, RangeDirective } from '@syncfusion/ej2-react-circulargauge';
export function App() {
return(
<CircularGaugeComponent
titleStyle={{
color: '#1976d2', // Dark blue
}}
background='#ffffff' // White
>
<AxesDirective>
<AxisDirective
labelStyle={{
color: '#424242', // Dark gray
}}
lineStyle={{
color: '#1976d2' // Dark blue
}}
>
<RangesDirective>
{/* Dark colors for ranges */}
<RangeDirective start={0} end={30} color='#1b5e20' />
<RangeDirective start={30} end={60} color='#f57f17' />
<RangeDirective start={60} end={100} color='#b71c1c' />
</RangesDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);
// ❌ Poor contrast (avoid)
<AxisDirective
labelStyle={{ color: '#ffff00' }} // Yellow on white - not enough contrast
background='#ffffff'
/>High Contrast Theme
<CircularGaugeComponent
background='#000000' // Black background
titleStyle={{ color: '#ffffff' }} // White text
>
<AxesDirective>
<AxisDirective
lineStyle={{ color: '#ffffff' }}
labelStyle={{ color: '#ffffff' }}
majorTicks={{ color: '#ffffff' }}
>
<RangesDirective>
<RangeDirective start={0} end={33} color='#00ff00' />
<RangeDirective start={33} end={66} color='#ffff00' />
<RangeDirective start={66} end={100} color='#ff0000' />
</RangesDirective>
<PointersDirective>
<PointerDirective value={50} color='#00ffff' />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>Focus Indicators
// Add custom CSS for focus indicators
const styles = `
.e-circulargauge:focus {
outline: 3px solid #1976d2;
outline-offset: 2px;
}
.e-circulargauge:focus-visible {
outline: 3px dashed #1976d2;
}
`;---
RTL (Right-to-Left) Support
Enable RTL
<CircularGaugeComponent
enableRtl={true}
direction='AntiClockWise' // Common for RTL languages
>
{/* gauge content */}
</CircularGaugeComponent>RTL Example with Arabic
import * as React from "react";
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
RangesDirective,
RangeDirective,
PointersDirective,
PointerDirective,
AnnotationDirective,
AnnotationsDirective
} from '@syncfusion/ej2-react-circulargauge';
export function App() {
return (
<CircularGaugeComponent
enableRtl={true}
title="مقياس الأداء"
titleStyle={{ size: '20px' }}
>
<AxesDirective>
<AxisDirective
minimum={0}
maximum={100}
direction="AntiClockWise"
>
<RangesDirective>
<RangeDirective start={0} end={30} color="#4caf50" label="جيد" />
<RangeDirective start={30} end={60} color="#fbc02d" label="عادي" />
<RangeDirective start={60} end={100} color="#f44336" label="سيء" />
</RangesDirective>
<PointersDirective>
<PointerDirective value={65} />
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content="القيمة الحالية"
radius="120%"
angle={90}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);---
Internationalization (i18n)
Locale Settings
import { setCulture } from '@syncfusion/ej2-base';
// Set culture for number formatting
setCulture('de-DE');
<CircularGaugeComponent locale="de-DE">
<AxesDirective>
<AxisDirective
labelStyle={{
format: '{value}'
}}
/>
</AxesDirective>
</CircularGaugeComponent>---
Number Formatting
// Different number formats by culture
<AxisDirective
labelStyle={{
format: '{value}' // Uses current culture
}}
minimum={0}
maximum={1000}
/>
// US: 1,000.50
// Germany: 1.000,50
// France: 1 000,50---
Currency Formatting
<AxisDirective
labelStyle={{
format: '${value}' // Manual prefix (not culture-aware)
}}
minimum={0}
maximum={1000}
/>
// Alternative formats
// format: '€{value}'
// format: '¥{value}'
// format: '£{value}'---
Multi-Language Example
import React, { useState } from 'react';
import { createRoot } from 'react-dom/client';
import { setCulture } from '@syncfusion/ej2-base';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
RangesDirective,
RangeDirective,
PointersDirective,
PointerDirective
} from '@syncfusion/ej2-react-circulargauge';
export function MultiLanguageGauge() {
const [language, setLanguage] = useState('en-US');
const labels: { [key: string]: any } = {
'en-US': {
title: 'Performance Gauge',
good: 'Good',
normal: 'Normal',
poor: 'Poor'
},
'de-DE': {
title: 'Leistungsmesser',
good: 'Gut',
normal: 'Normal',
poor: 'Schlecht'
},
'fr-FR': {
title: 'Jauge de Performance',
good: 'Bon',
normal: 'Normal',
poor: 'Mauvais'
}
};
const handleLanguageChange = (lang: string) => {
setLanguage(lang);
setCulture(lang);
};
const currentLabels = labels[language];
return (
<div>
<div>
<select onChange={(e) => handleLanguageChange(e.target.value)}>
<option value="en-US">English</option>
<option value="de-DE">Deutsch</option>
<option value="fr-FR">Français</option>
</select>
</div>
<CircularGaugeComponent
locale={language}
title={currentLabels.title}
>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<RangesDirective>
<RangeDirective
start={0}
end={30}
color='#4caf50'
label={currentLabels.good}
/>
<RangeDirective
start={30}
end={60}
color='#fbc02d'
label={currentLabels.normal}
/>
<RangeDirective
start={60}
end={100}
color='#f44336'
label={currentLabels.poor}
/>
</RangesDirective>
<PointersDirective>
<PointerDirective value={65} />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
const root = createRoot(document.getElementById('container')!);
root.render(<MultiLanguageGauge />);---
Accessibility Checklist
- [ ] Gauge has
aria-labeloraria-describedby - [ ] Text has sufficient color contrast (4.5:1 minimum)
- [ ] Keyboard navigation works (custom implementation required)
- [ ] Focus indicators are visible
- [ ] Screen reader announcements for value changes
- [ ] Semantic HTML structure
- [ ] Text alternatives for complex visualizations
- [ ] RTL support enabled for right-to-left languages
- [ ] Number formats respect user locale
- [ ] Labels are readable (not too small)
- [ ] No color as sole differentiator (use patterns/labels)
---
Tips and Best Practices
- Always provide descriptions: Don't rely only on visual representation
- Use aria-live: For real-time updates, announce changes to screen readers
- Test with screen readers: NVDA (Windows), JAWS, VoiceOver (Mac)
- Keyboard first: Ensure all functionality works without mouse
- Focus management: Keep focus visible during interactions
- Localization: Plan for text expansion in translations (German is ~20% longer than English)
- Symbols: Use consistent symbols/icons across cultures
- Testing: Include accessibility in your testing strategy
---
Notes
localemust be used along withsetCulture()for proper formattingsetCulture()sets global culture;localeapplies it to the component- Currency formats like
${value}are manual and not locale-aware - CircularGauge supports numeric formatting only (no date/time axis)
Advanced Features
Table of Contents
- Animation
- Enable Animation
- Pointer Animation
- Animation Timing
- Disabling Animation
- Animation on Value Change
- User Interaction
- Tooltip Configuration
- Tooltip Styling
- Custom Tooltip Template
- Mouse Events
- Print and Export
- Print Gauge
- Export to Image (PNG)
- Export to PDF
- All Export Options
- Export with Custom Filename
- Real-Time Data Binding
- Update Pointer Value
- Real-Time Updates with Interval
- API Data Binding
- WebSocket Real-Time Updates
- Event Handling
- Load Event
- Pointer Drag Events
- Range Interaction Events
- Gauge Mouse Events
- Tooltip & Annotation Events
- Axis Label Customization
- Multiple Gauge Instances
- Side-by-Side Gauges
- Dashboard with Multiple Gauges
- Responsive Multi-Gauge Layout
- Tips and Best Practices
Animation
Enable Animation
Animate pointer movements:
<CircularGaugeComponent
animationDuration={1000} // milliseconds
>
{/* gauge content */}
</CircularGaugeComponent>Pointer Animation
Control animation on individual pointers:
<PointerDirective
value={85}
type='Needle'
animation={{
enable: true,
duration: 1000, // milliseconds
delay: 0
}}
/>Animation Timing
Control animation behavior:
<PointerDirective
value={75}
animation={{
enable: true,
duration: 500, // Fast animation
delay: 100 // Delay before start
}}
/>
// Slow animation
<PointerDirective
value={60}
animation={{
enable: true,
duration: 2000, // 2 seconds
delay: 0
}}
/>Disabling Animation
<PointerDirective
value={50}
animation={{ enable: false }}
/>Animation on Value Change
Animate when pointer value changes:
import React, { useState } from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective }
from '@syncfusion/ej2-react-circulargauge';
export function AnimatedPointer() {
const [value, setValue] = useState(30);
const handleUpdate = () => {
// This triggers animation
setValue(75);
};
return (
<div>
<CircularGaugeComponent animationDuration={800}>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective
value={value}
animation={{
enable: true,
duration: 800
}}
/>
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
<button onClick={handleUpdate}>Update Value (Animated)</button>
</div>
);
}---
User Interaction
Tooltip Configuration
Display values on hover:
<CircularGaugeComponent
tooltip={{
enable: true,
type: TooltipType[] // 'Pointer' | 'Range' | 'Annotation'
}}
>
{/* gauge content */}
</CircularGaugeComponent>Tooltip Styling
<CircularGaugeComponent
tooltip={{
enable: true,
type: ['Pointer', 'Range'],
template: '{value}', // Custom format
fill: '#1976d2',
textStyle: {
color: '#ffffff',
size: '14px'
}
}}
>
{/* gauge content */}
</CircularGaugeComponent>Custom Tooltip Template
<CircularGaugeComponent
tooltip={{
enable: true,
template: '<div>Speed: {value} km/h</div>'
}}
>
{/* gauge content */}
</CircularGaugeComponent>Mouse Events
import React from 'react';
export function InteractiveGauge() {
const handleMouseMove = (args: any) => {
console.log('Mouse position:', args);
};
const handleMouseLeave = (args: any) => {
console.log('Mouse left gauge');
};
return (
<CircularGaugeComponent
gaugeMouseMove={handleMouseMove}
mouseLeaveEvent={handleMouseLeave}
>
{/* gauge content */}
</CircularGaugeComponent>
);
}---
Print and Export
Print Gauge
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { CircularGaugeComponent, Print, Inject } from '@syncfusion/ej2-react-circulargauge';
export function App() {
var gaugeInstance;
function clickHandler() {
gaugeInstance.print();
}
return (<div>
<ButtonComponent onClick={clickHandler}>
print
</ButtonComponent>
<CircularGaugeComponent
id="circulargauge"
allowPrint={true}
ref={(g) => (gaugeInstance = g)}
>
<Inject services={[Print]} />
</CircularGaugeComponent>
</div>
);
}
const root = ReactDOM.createRoot(document.getElementById('container'));
root.render(<App />);Export to Image (PNG)
import * as React from "react";
import * as ReactDOM from "react-dom";
import { ButtonComponent } from '@syncfusion/ej2-react-buttons';
import { CircularGaugeComponent, ImageExport, Inject } from '@syncfusion/ej2-react-circulargauge';
export function App() {
var gaugeInstance;
function clickHandler(){
gaugeInstance.export('PNG','Gauge');
}
return (<div>
<ButtonComponent onClick= {clickHandler}>Export</ButtonComponent>
<CircularGaugeComponent allowImageExport={true} ref={g => gaugeInstance = g}>
<Inject services={[ImageExport]} />
</CircularGaugeComponent>
</div>);
}
const root = ReactDOM.createRoot(document.getElementById('container'));
root.render(<App />);Export to PDF
var gaugeInstance;
function clickHandler(){
gaugeInstance.export('PDF','Gauge', 0);
}All Export Options
<div>
<button onClick={() => gaugeRef.current?.export('PNG', 'gauge.png')}>
Export PNG
</button>
<button onClick={() => gaugeRef.current?.export('PDF', 'gauge.pdf')}>
Export PDF
</button>
<button onClick={() => gaugeRef.current?.export('SVG', 'gauge.svg')}>
Export SVG
</button>
<button onClick={() => gaugeRef.current?.print()}>
Print
</button>
</div>Export with Custom Filename
const timestamp = new Date().toISOString().slice(0, 10);
gaugeRef.current?.export('PNG', `gauge-${timestamp}.png`);---
Real-Time Data Binding
Update Pointer Value
import React, { useState } from 'react';
import { CircularGaugeComponent,AxesDirective , AxisDirective, PointerDirective, PointersDirective} from '@syncfusion/ej2-react-circulargauge';
export function RealTimeGauge() {
const [value, setValue] = useState(50);
return (
<div>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective value={value} />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
<button onClick={() => setValue(Math.random() * 100)}>
Update Value
</button>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<RealTimeGauge />);Real-Time Updates with Interval
Monitor changing data:
import { createRoot } from 'react-dom/client';
import React, { useState } from 'react';
import { CircularGaugeComponent,AxesDirective , AxisDirective, PointerDirective, PointersDirective} from '@syncfusion/ej2-react-circulargauge';
import React, { useState, useEffect } from 'react';
export function RealtimeMonitor() {
const [value, setValue] = useState(50);
useEffect(() => {
// Simulate real-time data
const interval = setInterval(() => {
const newValue = 40 + Math.random() * 60; // Random 40-100
setValue(newValue);
}, 1000);
return () => clearInterval(interval);
}, []);
return (
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective
value={value}
animation={{ enable: true, duration: 500 }}
/>
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeMonitor />);API Data Binding
Fetch and display real data:
import React, { useState } from 'react';
import { CircularGaugeComponent,AxesDirective , AxisDirective, PointerDirective, PointersDirective} from '@syncfusion/ej2-react-circulargauge';
import React, { useState, useEffect } from 'react';
export function APIBoundGauge() {
const [sensorData, setSensorData] = useState(0);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchData = async () => {
try {
// Example API call
const response = await fetch('/api/sensor/temperature');
const data = await response.json();
setSensorData(data.value);
setLoading(false);
} catch (error) {
console.error('Error fetching data:', error);
setLoading(false);
}
};
// Initial fetch
fetchData();
// Poll every 5 seconds
const interval = setInterval(fetchData, 5000);
return () => clearInterval(interval);
}, []);
if (loading) return <div>Loading...</div>;
return (
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective value={sensorData} />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<APIBoundGauge />);WebSocket Real-Time Updates
import React, { useState } from 'react';
import { CircularGaugeComponent,AxesDirective , AxisDirective, PointerDirective, PointersDirective} from '@syncfusion/ej2-react-circulargauge';
import React, { useState, useEffect } from 'react';
export function WebSocketGauge() {
const [value, setValue] = useState(50);
useEffect(() => {
const ws = new WebSocket('ws://localhost:8080/gauge');
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
setValue(data.value);
};
return () => ws.close();
}, []);
return (
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective value={value} />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<WebSocketGauge />);---
Event Handling
See API Reference for full event arg types and method signatures.
Load Event
Handle gauge initialization:
<CircularGaugeComponent
load={(args: ILoadEventArgs) => {
console.log('Before gauge load:', args);
}}
loaded={(args: ILoadedEventArgs) => {
console.log('Gauge fully rendered:', args);
}}
resized={(args: IResizeEventArgs) => {
console.log('Gauge resized:', args);
}}
animationComplete={(args: IAnimationCompleteEventArgs) => {
console.log('Animation completed:', args);
}}
>
{/* gauge content */}
</CircularGaugeComponent>Pointer Drag Events
<CircularGaugeComponent
enablePointerDrag={true}
pointerDragStart={(args: IPointerDragEventArgs) => {
console.log('Pointer drag started:', args.currentValue);
}}
pointerDragMove={(args: IPointerDragEventArgs) => {
console.log('Pointer dragging:', args.currentValue);
}}
pointerDragEnd={(args: IPointerDragEventArgs) => {
console.log('Pointer drag ended:', args.currentValue);
}}
>
{/* gauge content */}
</CircularGaugeComponent>Range Interaction Events
<CircularGaugeComponent
rangeMouseClick={(args: IMouseEventArgs) => {
console.log('Range clicked:', args);
}}
rangeMouseMove={(args: IMouseEventArgs) => {
console.log('Range hover:', args);
}}
rangeMouseLeave={(args: IMouseEventArgs) => {
console.log('Range leave:', args);
}}
>
{/* gauge content */}
</CircularGaugeComponent>Gauge Mouse Events
<CircularGaugeComponent
gaugeMouseMove={(args: IMouseEventArgs) => {
console.log('Mouse move:', args);
}}
gaugeMouseLeave={(args: IMouseEventArgs) => {
console.log('Mouse leave:', args);
}}
gaugeMouseDown={(args: IMouseEventArgs) => {
console.log('Mouse down:', args);
}}
gaugeMouseUp={(args: IMouseEventArgs) => {
console.log('Mouse up:', args);
}}
>
{/* gauge content */}
</CircularGaugeComponent>Tooltip & Annotation Events
<CircularGaugeComponent
tooltipRender={(args: ITooltipRenderEventArgs) => {
args.content = [`Value: ${args.currentValue}`];
}}
annotationRender={(args: IAnnotationRenderEventArgs) => {
console.log('Annotation rendering:', args);
}}
>
{/* gauge content */}
</CircularGaugeComponent>Axis Label Customization
<CircularGaugeComponent
axisLabelRender={(args: IAxisLabelRenderEventArgs) => {
args.text = `${args.text}°`;
}}
>
{/* gauge content */}
</CircularGaugeComponent>Complete Event Example
import React, { useState } from 'react';
import { CircularGaugeComponent} from '@syncfusion/ej2-react-circulargauge';
import React, { useState, useEffect } from 'react';
export function EventHandlingGauge() {
const [lastEvent, setLastEvent] = useState('');
return (
<div>
<CircularGaugeComponent
load={() => setLastEvent('Gauge loaded')}
pointerDragMove={(args) => setLastEvent(`Pointer value: ${args.value}`)}
rangeMouseClick={() => setLastEvent('Range clicked')}
>
{/* gauge content */}
</CircularGaugeComponent>
<p>Last Event: {lastEvent}</p>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<EventHandlingGauge />);---
Multiple Gauge Instances
Side-by-Side Gauges
import React from 'react';
import { CircularGaugeComponent,AxesDirective , AxisDirective, PointerDirective, PointersDirective} from '@syncfusion/ej2-react-circulargauge';
import React, { useState, useEffect } from 'react';
export function App() {
return (
<div style={{
display: 'grid',
gridTemplateColumns: '1fr 1fr',
gap: '20px'
}}>
<div style={{ height: '400px' }}>
<CircularGaugeComponent title="Temperature">
<AxesDirective>
<AxisDirective minimum={0} maximum={50}>
<PointersDirective>
<PointerDirective value={25} />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
<div style={{ height: '400px' }}>
<CircularGaugeComponent title="Humidity">
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective value={65} />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);Dashboard with Multiple Gauges
import React, { useState, useEffect } from 'react';
import { CircularGaugeComponent,AxesDirective , AxisDirective, PointerDirective, PointersDirective,RangesDirective,RangeDirective } from '@syncfusion/ej2-react-circulargauge';
export function DashboardGauges() {
const [metrics, setMetrics] = useState({
cpu: 45,
memory: 60,
disk: 75,
network: 30
});
useEffect(() => {
const interval = setInterval(() => {
setMetrics({
cpu: 30 + Math.random() * 50,
memory: 40 + Math.random() * 40,
disk: Math.random() * 100,
network: Math.random() * 100
});
}, 2000);
return () => clearInterval(interval);
}, []);
return (
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: '20px',
padding: '20px'
}}>
{Object.entries(metrics).map(([label, value]) => (
<div key={label} style={{ height: '400px' }}>
<CircularGaugeComponent title={label.toUpperCase()}>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<RangesDirective>
<RangeDirective start={0} end={30} color='#4caf50' />
<RangeDirective start={30} end={60} color='#fbc02d' />
<RangeDirective start={60} end={100} color='#f44336' />
</RangesDirective>
<PointersDirective>
<PointerDirective
value={value}
animation={{ enable: true, duration: 500 }}
/>
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
))}
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<DashboardGauges />);Responsive Multi-Gauge Layout
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '20px',
justifyContent: 'space-around'
}}>
{/* Gauge 1 */}
<div style={{
flex: '1 1 calc(50% - 10px)',
minWidth: '250px',
height: '400px'
}}>
<CircularGaugeComponent>
{/* content */}
</CircularGaugeComponent>
</div>
{/* Gauge 2 */}
<div style={{
flex: '1 1 calc(50% - 10px)',
minWidth: '250px',
height: '400px'
}}>
<CircularGaugeComponent>
{/* content */}
</CircularGaugeComponent>
</div>
{/* Gauge 3 */}
<div style={{
flex: '1 1 calc(50% - 10px)',
minWidth: '250px',
height: '400px'
}}>
<CircularGaugeComponent>
{/* content */}
</CircularGaugeComponent>
</div>
</div>---
Tips and Best Practices
- Animation duration: Keep under 1000ms for responsive feel
- Export format: Use PNG for web, SVG for printing with high quality
- Real-time updates: Throttle updates to ~1000ms for performance
- Event handling: Avoid heavy computations in event handlers
- Multiple gauges: Limit to 4-6 on one screen to avoid performance issues
- Tooltips: Enable only when necessary to avoid cluttering
Annotations & Legend
See the API quick reference: api-reference.md for annotation and legend model properties (e.g., AnnotationDirective, legendSettings).
Table of Contents
- Text Annotations
- Basic Text Annotation
- Text Styling
- Multiple Text Annotations
- HTML Content in Annotations
- Annotation with Positioning Units
- Center Annotation
- Dynamic Annotation Positioning
- Image Annotations
- Basic Image Annotation
- Image with Custom Size
- Image with Text Overlay
- Multiple Image Annotations
- Annotation Positioning
- Angle-Based Positioning
- Radius-Based Positioning
- Legend Display
- Basic Legend
- Legend Positions
- Legend Styling
- Legend with Title
- Legend Customization
- Range Labels in Legend
- Legend Shape and Icon
- Legend Text Formatting
- Legend Interactions
- Toggle Legend Visibility
- Legend Item Click Event
- Custom Legend Item Render
- Dynamic Legend Updates
- Complete Example: Dashboard with Annotations and Legend
- Tips and Best Practices
Text Annotations
Basic Text Annotation
Add text labels to the gauge:
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
AnnotationsDirective,
AnnotationDirective,
} from '@syncfusion/ej2-react-circulargauge';
export function App() {
return (
<CircularGaugeComponent >
<AxesDirective>
<AxisDirective>
{/* pointer and range content */}
<AnnotationsDirective>
<AnnotationDirective content="90 mph" angle={0} radius="100%" />
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);
Text Styling
Customize annotation appearance:
<AnnotationDirective
content="Speed: 120 km/h"
angle={0}
radius="100%"
textStyle={{
color: '#1976d2',
size: '18px',
fontFamily: 'Arial',
fontWeight: 'bold'
}}
/>Multiple Text Annotations
Add multiple labels:
<AnnotationsDirective>
<AnnotationDirective
content="Min: 0"
angle={270}
radius="90%"
textStyle={{ size: '14px' }}
/>
<AnnotationDirective
content="Max: 120"
angle={90}
radius="90%"
textStyle={{ size: '14px' }}
/>
<AnnotationDirective
content="Current Speed"
angle={0}
radius="120%"
textStyle={{ size: '16px', fontWeight: 'bold' }}
/>
</AnnotationsDirective>HTML Content in Annotations
Use HTML for rich formatting:
<AnnotationDirective
content="<div style='background: #1976d2; color: white; padding: 8px; border-radius: 4px;'>75°C</div>"
angle={180}
radius="0%"
/>Annotation with Positioning Units
// Percentage of gauge radius
<AnnotationDirective
content="50%"
radius="50%"
angle={90}
/>
// Pixels
<AnnotationDirective
content="100px"
radius="100px"
angle={45}
/>---
Image Annotations
Basic Image Annotation
Add an image to the gauge:
<AnnotationsDirective>
<AnnotationDirective
imageUrl="./assets/speedometer-icon.png"
angle={0}
radius="100%"
description="Speed Icon"
/>
</AnnotationsDirective>Image with Custom Size
<AnnotationDirective
imageUrl="./assets/temperature-icon.svg"
angle={90}
radius="80%"
imageWidth={40}
imageHeight={40}
/>Image with Text Overlay
Combine image and text:
<AnnotationsDirective>
<AnnotationDirective
imageUrl="./assets/status-ok.png"
angle={180}
radius="110%"
imageWidth={32}
imageHeight={32}
/>
<AnnotationDirective
content="OK"
angle={180}
radius="130%"
textStyle={{ size: '16px', fontWeight: 'bold' }}
/>
</AnnotationsDirective>Multiple Image Annotations
<AnnotationsDirective>
<AnnotationDirective
imageUrl="./assets/arrow-up.svg"
angle={0}
radius="50%"
imageWidth={20}
imageHeight={20}
/>
<AnnotationDirective
imageUrl="./assets/arrow-down.svg"
angle={180}
radius="50%"
imageWidth={20}
imageHeight={20}
/>
</AnnotationsDirective>---
Annotation Positioning
Angle-Based Positioning
Position annotations around the circle using angles:
// 0° = right (3 o'clock)
// 90° = bottom (6 o'clock)
// 180° = left (9 o'clock)
// 270° = top (12 o'clock)
<AnnotationsDirective>
<AnnotationDirective content="Right" angle={0} radius="100%" />
<AnnotationDirective content="Bottom" angle={90} radius="100%" />
<AnnotationDirective content="Left" angle={180} radius="100%" />
<AnnotationDirective content="Top" angle={270} radius="100%" />
<AnnotationDirective content="Diagonal" angle={45} radius="100%" />
</AnnotationsDirective>Radius-Based Positioning
Position closer to or farther from center:
<AnnotationsDirective>
{/* Close to center */}
<AnnotationDirective content="Inner" radius="20%" angle={0} />
{/* Middle */}
<AnnotationDirective content="Middle" radius="60%" angle={90} />
{/* Outer (beyond gauge) */}
<AnnotationDirective content="Outer" radius="120%" angle={180} />
</AnnotationsDirective>Center Annotation
Add text in the center of the gauge:
<AnnotationDirective
content="75%"
radius="0%"
angle={0}
textStyle={{
size: '24px',
fontWeight: 'bold',
color: '#1976d2'
}}
/>Dynamic Annotation Positioning
Position annotation based on pointer value:
import React, { useState } from 'react';
export function DynamicAnnotation() {
const [value, setValue] = useState(50);
// Calculate angle based on pointer value
// Assuming 0-100 scale across 180° (semicircle)
const angle = 270 + (value * 1.8); // 270° to 90°
return (
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<AnnotationsDirective>
<AnnotationDirective
content={`${value}%`}
angle={angle}
radius="100%"
textStyle={{ size: '16px' }}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}---
Legend Display
Basic Legend
Display a legend showing range meanings:
import { CircularGaugeComponent, AxesDirective, AxisDirective,
RangesDirective, RangeDirective, Inject, Legend }
from '@syncfusion/ej2-react-circulargauge';
<CircularGaugeComponent
legendSettings={{
visible: true,
position: 'Auto' // Auto, Top, Bottom, Left, Right, Custom
}}
>
<Inject services={[ Legend ]}/>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<RangesDirective>
<RangeDirective
start={0}
end={30}
color='#4caf50'
legendText='Low'
radius='108%'
/>
<RangeDirective
start={30}
end={60}
color='#fbc02d'
legendText='Medium'
radius='108%'
/>
<RangeDirective
start={60}
end={100}
color='#f44336'
legendText='High'
radius='108%'
/>
</RangesDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>Legend Positions
// Auto (default)
legendSettings={{ visible: true, position: 'Auto' }}
// Top
legendSettings={{ visible: true, position: 'Top' }}
// Bottom
legendSettings={{ visible: true, position: 'Bottom' }}
// Left
legendSettings={{ visible: true, position: 'Left' }}
// Right
legendSettings={{ visible: true, position: 'Right' }}
// Custom - position using location
legendSettings={{
visible: true,
position: 'Custom',
location: { x: 100, y: 150 }
}}Legend Styling
Customize legend appearance:
<CircularGaugeComponent
legendSettings={{
visible: true,
position: 'Bottom', // Top, Bottom, Left, Right, Custom, Auto
alignment: 'Center', // Center, Far, Near
height: '50px',
width: '100%',
background: '#f5f5f5',
opacity: 1,
padding: 8,
border: {
color: '#e0e0e0',
width: 1
},
textStyle: {
color: '#424242',
size: '14px',
fontFamily: 'Segoe UI',
fontStyle: 'Normal',
fontWeight: 'Normal'
},
toggleVisibility: true,
shape: 'Circle', // Circle, Rectangle, Diamond, Triangle, InvertedTriangle, Image
shapeWidth: 10,
shapeHeight: 10,
shapePadding: 5,
shapeBorder: {
color: '#e0e0e0',
width: 1
},
margin: {
top: 10,
bottom: 10,
left: 10,
right: 10
}
}}
>
{/* gauge content */}
</CircularGaugeComponent>Legend Customization
Range Labels in Legend
Control what appears in the legend using legendText property:
<RangesDirective>
<RangeDirective
start={0}
end={30}
color='#4caf50'
legendText='Safe (0-30%)'
radius='108%'
/>
<RangeDirective
start={30}
end={60}
color='#fbc02d'
legendText='Caution (30-60%)'
radius='108%'
/>
<RangeDirective
start={60}
end={100}
color='#f44336'
legendText='Danger (60-100%)'
radius='108%'
/>
</RangesDirective>Legend Shape and Icon
<CircularGaugeComponent
legendSettings={{
visible: true,
shape: 'Circle', // Circle, Rectangle, Triangle, InvertedTriangle, Diamond, Image
shapeWidth: 30,
shapeHeight: 30,
shapePadding: 5,
shapeBorder: {
color: '#e0e0e0',
width: 1
}
}}
>
{/* gauge content */}
</CircularGaugeComponent>Legend Text Formatting
<CircularGaugeComponent
legendSettings={{
visible: true,
toggleVisibility: true,
textStyle: {
color: '#424242',
size: '14px',
fontFamily: 'Segoe UI',
fontStyle: 'Normal',
fontWeight: 'Normal',
opacity: 0.8
}
}}
>
{/* gauge content */}
</CircularGaugeComponent>---
Legend Interactions
Toggle Legend Visibility
Allow users to toggle visibility of ranges:
<CircularGaugeComponent
legendSettings={{
visible: true,
toggleVisibility: true // Click legend item to toggle range
}}
>
{/* gauge content */}
</CircularGaugeComponent>Legend Item Click Event
Handle legend item clicks:
import React, { useState } from 'react';
export function InteractiveLegend() {
const [ranges, setRanges] = useState([
{ start: 0, end: 30, visible: true },
{ start: 30, end: 60, visible: true },
{ start: 60, end: 100, visible: true }
]);
const handleLegendItemClick = (e: any) => {
console.log('Legend item clicked:', e.data);
// Handle toggle logic
};
return (
<CircularGaugeComponent
legendSettings={{
visible: true,
toggleVisibility: true
}}
legendRender={handleLegendItemClick}
>
{/* gauge content */}
</CircularGaugeComponent>
);
}Custom Legend Item Render
Use the legendRendering event to customize legend items before rendering:
<CircularGaugeComponent
legendRendering={(args: any) => {
// Customize legend item before render
if (args.text.includes('High')) {
args.shape = 'Diamond';
}
// You can also customize: fill, text, shape, name, cancel
}}
legendSettings={{ visible: true }}
>
{/* gauge content */}
</CircularGaugeComponent>Dynamic Legend Updates
Update legend when ranges change:
import React, { useEffect, useRef } from 'react';
export function DynamicLegend() {
const gaugeRef = useRef<CircularGaugeComponent>(null);
useEffect(() => {
// Update ranges dynamically
const updatedRanges = [
{ start: 0, end: 25, color: '#4caf50', label: 'Optimal' },
{ start: 25, end: 50, color: '#fbc02d', label: 'Normal' },
{ start: 50, end: 100, color: '#f44336', label: 'Alert' }
];
// Refresh gauge with new ranges
if (gaugeRef.current) {
gaugeRef.current.refresh();
}
}, []);
return (
<CircularGaugeComponent
ref={gaugeRef}
legendSettings={{ visible: true }}
>
{/* gauge content */}
</CircularGaugeComponent>
);
}---
Complete Example: Dashboard with Annotations and Legend
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective, RangesDirective, RangeDirective,
AnnotationsDirective, AnnotationDirective, Inject, Legend }
from '@syncfusion/ej2-react-circulargauge';
export function CompleteDashboard() {
return (
<CircularGaugeComponent
legendSettings={{
visible: true,
position: 'Bottom',
alignment: 'Center',
shape: 'Circle',
shapeWidth: 30,
shapeHeight: 30,
padding: 15,
border: {
color: 'green',
width: 3
}
}}
>
<Inject services={[ Legend ]}/>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<RangesDirective>
<RangeDirective
start={0}
end={30}
color='#4caf50'
legendText='Good'
radius='108%'
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={30}
end={60}
color='#fbc02d'
legendText='Normal'
radius='108%'
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={60}
end={100}
color='#f44336'
legendText='Poor'
radius='108%'
startWidth={10}
endWidth={10}
/>
</RangesDirective>
<PointersDirective>
<PointerDirective value={75} type='Needle' />
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content="75%"
radius="0%"
angle={0}
textStyle={{ size: '20px', fontWeight: 'bold' }}
/>
<AnnotationDirective
content="Current Status"
radius="120%"
angle={90}
textStyle={{ size: '14px' }}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}---
Tips and Best Practices
- Use meaningful labels: Legend labels should clearly describe what ranges represent
- Position annotations carefully: Avoid overlapping with pointers or other elements
- Limit annotations: Too many annotations clutter the gauge
- Color consistency: Use legend colors that match range colors exactly
- Test positioning: Verify annotations display correctly at different gauge sizes
- HTML content: Keep HTML annotations simple and lightweight
Circular Gauge API Reference
This file summarizes the main component-level API for CircularGaugeComponent. Use it as a quick lookup for props, methods and events. For full details, consult the official docs.
Component Props
Core
axes: AxisModel[]— Axis configuration arraybackground: string— Gauge background colorborder: BorderModel— Border configurationcenterX / centerY: string— Gauge center position (%, px)
---
Interaction & Behavior
enablePointerDrag: boolean— Enable pointer draggingenableRangeDrag: boolean— Enable range draggingenableRtl: boolean— Enable RTL layoutenablePersistence: boolean— Persist state across reloadsenableGroupingSeparator: boolean— Format labels with grouping separatorsenableAnimation: boolean— Enable animationsenableBorderOnMouseMove: boolean— Highlight border on hoverenableHtmlSanitizer: boolean— Sanitize HTML content
---
Layout & Appearance
height / width: string | number— Dimensionsmargin: MarginModel— Outer marginmoveToCenter: boolean— Move gauge to centerradius: string— Radius of the gaugetheme: GaugeTheme— Theme nametitle: string— Title texttitleStyle: FontModel— Title styling
---
Export & Utilities
allowImageExport: boolean— Enable image exportallowPdfExport: boolean— Enable PDF exportallowPrint: boolean— Enable printingallowMargin: boolean— Auto margin calculation
---
Accessibility
description: string— Accessibility descriptiontabIndex: number— Keyboard navigation index
---
Localization
locale: string— Locale code
---
Tooltip & Legend
tooltip: TooltipSettingsModel— Tooltip configurationlegendSettings: LegendSettingsModel— Legend configuration
---
Animation
animationDuration: number— Global animation duration (ms)
---
Notes
enableGroupingSeparatorreplaces incorrectuseGroupingSeparatoraxesis required for rendering- Properties like
enableAnimationandradiusare commonly used but often missed
Methods
destroy(): void— Destroys the widget and removes event handlers (see Methods: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default#methods)export(type: 'PNG'|'JPEG'|'SVG'|'PDF', fileName?: string, orientation?: any, allowDownload?: boolean): Promise<any>— Export gauge (see Methods: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default#methods)print(id?: string | string[] | Element): void— Print gauge element(s) (see Methods: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default#methods)setAnnotationValue(axisIndex: number, annotationIndex: number, content: string | Function): void— Update annotation content (see Methods: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default#methods)setPointerValue(axisIndex: number, pointerIndex: number, value: number): void— Set pointer value programmatically (see Methods: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default#methods)setRangeValue(axisIndex: number, rangeIndex: number, start: number, end: number): void— Update range start/end values (see Methods: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default#methods)refresh(): void— Refreshes the gauge and re-renders the component
Events (selected)
animationComplete— Fired after animations complete (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/ianimationcompleteeventargs)annotationRender— Fired when an annotation is rendered (use to customize content) (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iannotationrendereventargs)axisLabelRender— Fired when axis label is rendered (can cancel or modify label) (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iaxislabelrendereventargs)beforePrint— Fired before printing (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iprinteventargs)dragStart/dragMove/dragEnd— Pointer drag lifecycle events (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/ipointerdrageventargs)gaugeMouseDown/gaugeMouseMove/gaugeMouseUp/gaugeMouseLeave— Mouse interaction events (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/imouseeventargs)legendRender— Fired before legend item render (use to customize legend) (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/ilegendrendereventargs)load— Fired before the gauge is rendered (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iloadedeventargs)loaded— Fired after the gauge is rendered (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iloadedeventargs)radiusCalculate— Fired during radius calculation (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iradiuscalculateeventargs)resized— Fired after gauge is resized (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/iresizeeventargs)tooltipRender— Fired before tooltip shows (modify or cancel) (args: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/itooltiprendereventargs)tooltipRenderComplete— Fired after tooltip is rendered
Child Directives & Models
AxesDirective/AxisDirective— Axis configuration wrapperPointersDirective/PointerDirective— Pointer definitions (properties:value,type,radius,pointerWidth,color,enableDrag,cap,needleTail,imageUrl, etc.)RangesDirective/RangeDirective— Range definitions (properties:start,end,color,startWidth,endWidth,opacity,roundedCorners)AnnotationsDirective/AnnotationDirective— Annotations (properties:content,angle,radius,textStyle,imageUrl)
Quick examples
- Programmatically update pointer value:
// set pointer value for axis 0, pointer 0
gaugeRef.current?.setPointerValue(0, 0, 75);- Update an annotation HTML content:
gaugeRef.current?.setAnnotationValue(0, 0, `<div style="font-size:14px;">Value: ${value}</div>`);- Export gauge as PNG:
await gaugeRef.current?.export('PNG', 'my-gauge');---
For full, authoritative reference with complete type definitions and examples, see the official docs: https://ej2.syncfusion.com/react/documentation/api/circular-gauge/index-default
Appearance & Dimensions
Reference the API quick guide: api-reference.md for prop names such as centerX, centerY, width, height, and background.
Table of Contents
- Gauge Title
- Adding a Title
- Title Customization
- Title Positioning
- Gauge Position
- Center Position
- Percentage (Recommended)
- In Pixels
- Common Positioning Examples
- Gauge Dimensions
- Width and Height
- Responsive Sizing
- Margins
- Gauge Background and Borders
- Background Color
- Border Styling
- Shadow Effects
- Colors and Styling
- Color Scheme Example
- Dark Mode
- Gradient and Advanced Styling
- Responsive Design
- Mobile-First Approach
- CSS Media Queries
- Flexbox Layout
- Container Setup
- Basic Container
- Container with Padding and Borders
- Grid Layout with Multiple Gauges
- Card-Style Container
- Tips and Best Practices
---
Gauge Title
Adding a Title
Display a title at the top of the gauge:
<CircularGaugeComponent
title="Speed (km/h)"
>
{/* gauge content */}
</CircularGaugeComponent>Title Customization
Customize title appearance with titleStyle:
<CircularGaugeComponent
title="Dashboard KPI"
titleStyle={{
size: '24px',
color: '#1976d2',
fontFamily: 'Arial, sans-serif',
fontWeight: 'bold',
alignment: 'Center', // Center, Far, Near
opacity: 1
}}
>
{/* gauge content */}
</CircularGaugeComponent>Title Positioning
The title always appears at the top-center by default. To create custom layouts, use CSS:
<div style={{ position: 'relative' }}>
<h2 style={{ textAlign: 'center', marginBottom: '10px' }}>
Custom Title Position
</h2>
<CircularGaugeComponent>
{/* No title prop, using CSS above */}
</CircularGaugeComponent>
</div>---
Gauge Position
Center Position
The gauge is positioned within its container using centerX and centerY. These values can be in percentage or pixels:
Percentage (Recommended)
Position relative to the container:
<CircularGaugeComponent
centerX="50%" // Horizontal center (default)
centerY="50%" // Vertical center (default)
>
{/* gauge content */}
</CircularGaugeComponent>Percentage positioning is responsive and works well with various container sizes.
In Pixels
Absolute pixel positioning:
<CircularGaugeComponent
centerX="200px" // 200 pixels from left
centerY="150px" // 150 pixels from top
>
{/* gauge content */}
</CircularGaugeComponent>Common Positioning Examples
// Top-left corner
<CircularGaugeComponent centerX="25%" centerY="25%" />
// Top-center
<CircularGaugeComponent centerX="50%" centerY="25%" />
// Top-right corner
<CircularGaugeComponent centerX="75%" centerY="25%" />
// Left side
<CircularGaugeComponent centerX="20%" centerY="50%" />
// Center (default)
<CircularGaugeComponent centerX="50%" centerY="50%" />
// Right side
<CircularGaugeComponent centerX="80%" centerY="50%" />
// Bottom-left corner
<CircularGaugeComponent centerX="25%" centerY="75%" />
// Bottom-center
<CircularGaugeComponent centerX="50%" centerY="75%" />
// Bottom-right corner
<CircularGaugeComponent centerX="75%" centerY="75%" />---
Gauge Dimensions
Width and Height
Set explicit dimensions or use CSS:
// Option 1: Wrap in div with size
<div style={{ width: '600px', height: '600px' }}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>
// Option 2: Use component props
<CircularGaugeComponent
width="600"
height="600"
>
{/* gauge content */}
</CircularGaugeComponent>Note: Circular gauges work best when width and height are equal to maintain a perfect circle.
Responsive Sizing
For responsive designs, use viewport units or percentages:
<div style={{
width: '100%',
maxWidth: '600px',
height: 'auto',
aspectRatio: '1' // Maintain square aspect
}}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>Margins
Add margin to the gauge using container CSS:
<div style={{
width: '100%',
height: '500px',
margin: '20px auto', // Auto horizontal centers
padding: '20px'
}}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>---
Gauge Background and Borders
Background Color
Set the gauge background:
<CircularGaugeComponent
background='#ffffff' // White background
>
{/* gauge content */}
</CircularGaugeComponent>
// Transparent
<CircularGaugeComponent
background='transparent'
>
{/* gauge content */}
</CircularGaugeComponent>
// Semi-transparent
<CircularGaugeComponent
background='rgba(255, 255, 255, 0.95)'
>
{/* gauge content */}
</CircularGaugeComponent>Border Styling
Add border to the gauge container:
<div style={{
width: '500px',
height: '500px',
border: '2px solid #1976d2',
borderRadius: '8px',
overflow: 'hidden'
}}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>Shadow Effects
Add shadow for depth:
<div style={{
width: '500px',
height: '500px',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.15)',
borderRadius: '8px'
}}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>---
Colors and Styling
Color Scheme Example
Create a cohesive color scheme:
<CircularGaugeComponent
background='#f5f5f5'
title='Performance Gauge'
titleStyle={{ color: '#1976d2' }}
>
<AxesDirective>
<AxisDirective
lineStyle={{ width: 2, color: '#1976d2' }}
majorTicks={{ color: '#1976d2' }}
minorTicks={{ color: '#90caf9' }}
labelStyle={{ color: '#424242' }}
>
<RangesDirective>
<RangeDirective start={0} end={33} color='#4caf50' startWidth={10} endWidth={10} />
<RangeDirective start={33} end={66} color='#fbc02d' startWidth={10} endWidth={10} />
<RangeDirective start={66} end={100} color='#f44336' startWidth={10} endWidth={10} />
</RangesDirective>
<PointersDirective>
<PointerDirective value={60} type='Needle' color='#1976d2' />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>Dark Mode
Create a dark-themed gauge:
<div style={{ backgroundColor: '#212121', padding: '20px', borderRadius: '8px' }}>
<CircularGaugeComponent
background='#1e1e1e'
title='Dark Mode Gauge'
titleStyle={{ color: '#ffffff' }}
>
<AxesDirective>
<AxisDirective
lineStyle={{ color: '#4a4a4a' }}
labelStyle={{ color: '#e0e0e0' }}
>
<RangesDirective>
<RangeDirective start={0} end={100} color='#404040' startWidth={10} endWidth={10} />
</RangesDirective>
<PointersDirective>
<PointerDirective value={60} type='Needle' color='#81c784' />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>Gradient and Advanced Styling
Use CSS for gradient backgrounds:
<div style={{
width: '500px',
height: '500px',
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
padding: '20px',
borderRadius: '8px'
}}>
<CircularGaugeComponent
background='rgba(255, 255, 255, 0.95)'
>
{/* gauge content */}
</CircularGaugeComponent>
</div>---
Responsive Design
Mobile-First Approach
import React, { useState, useEffect } from 'react';
import { CircularGaugeComponent} from '@syncfusion/ej2-react-circulargauge';
export function ResponsiveGauge() {
const [size, setSize] = useState({
width: window.innerWidth,
height: window.innerHeight
});
useEffect(() => {
const handleResize = () => {
setSize({
width: window.innerWidth,
height: window.innerHeight
});
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const gaugeSize = Math.min(size.width, size.height) * 0.8;
return (
<div style={{
width: '100%',
height: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}}>
<div style={{
width: `${gaugeSize}px`,
height: `${gaugeSize}px`
}}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>
</div>
);
}CSS Media Queries
<div className="gauge-container">
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>.gauge-container {
width: 100%;
height: 100%;
min-height: 500px;
}
/* Tablet */
@media (max-width: 768px) {
.gauge-container {
min-height: 400px;
}
}
/* Mobile */
@media (max-width: 480px) {
.gauge-container {
min-height: 300px;
}
}Flexbox Layout
<div style={{
display: 'flex',
flexWrap: 'wrap',
gap: '20px',
padding: '20px'
}}>
<div style={{ flex: 1, minWidth: '300px', height: '400px' }}>
<CircularGaugeComponent>
{/* Gauge 1 */}
</CircularGaugeComponent>
</div>
<div style={{ flex: 1, minWidth: '300px', height: '400px' }}>
<CircularGaugeComponent>
{/* Gauge 2 */}
</CircularGaugeComponent>
</div>
</div>---
Container Setup
Basic Container
<div style={{ height: '500px' }}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>Container with Padding and Borders
<div style={{
height: '600px',
padding: '20px',
border: '1px solid #e0e0e0',
borderRadius: '4px',
backgroundColor: '#fafafa'
}}>
<CircularGaugeComponent
centerX="50%"
centerY="50%"
>
{/* gauge content */}
</CircularGaugeComponent>
</div>Grid Layout with Multiple Gauges
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: '20px',
padding: '20px'
}}>
<div style={{ height: '400px' }}>
<CircularGaugeComponent>
{/* Gauge 1 */}
</CircularGaugeComponent>
</div>
<div style={{ height: '400px' }}>
<CircularGaugeComponent>
{/* Gauge 2 */}
</CircularGaugeComponent>
</div>
<div style={{ height: '400px' }}>
<CircularGaugeComponent>
{/* Gauge 3 */}
</CircularGaugeComponent>
</div>
</div>Card-Style Container
<div style={{
width: '100%',
maxWidth: '500px',
margin: '20px auto',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.1)',
borderRadius: '8px',
overflow: 'hidden'
}}>
<div style={{
backgroundColor: '#1976d2',
color: '#fff',
padding: '16px',
fontSize: '18px',
fontWeight: 'bold'
}}>
Performance Metrics
</div>
<div style={{ height: '500px' }}>
<CircularGaugeComponent
centerX="50%"
centerY="50%"
>
{/* gauge content */}
</CircularGaugeComponent>
</div>
</div>---
Tips and Best Practices
- Always set container height: Gauges require explicit height to render properly
- Use percentage positioning:
centerXandcenterYwith percentages adapt better to container changes - Match width and height: For perfect circular gauges, use equal width and height
- Responsive containers: Use flexbox or CSS Grid for multi-gauge layouts
- Theme consistency: Choose one theme and stick with it across your application
- Color contrast: Ensure labels and pointers have sufficient contrast with background
Axes, Pointers & Ranges
See the API quick reference: api-reference.md for exact prop and child directive names (e.g., PointersDirective, RangeDirective, setPointerValue).
Table of Contents
- Axis Customization
- Line Style
- Axis Background
- Complete Axis Styling Example
- Axis Angles and Direction
- Start and End Angles
- Axis Direction
- Common Angle Combinations
- Axis Scale and Labels
- Minimum and Maximum Values
- Major and Minor Ticks
- Labels
- Pointer Types
- Needle Pointer (Default)
- RangeBar Pointer
- Marker Pointer
- Needle Pointer
- Basic Needle Configuration
- Needle with Cap and Tail
- Styled Speedometer Needle
- RangeBar Pointer
- Basic RangeBar
- RangeBar with Rounded Corners
- Multiple RangeBars (Progress Layers)
- Marker Pointer
- Basic Marker
- Different Marker Shapes
- Custom Marker with Image
- Styled Marker
- Ranges
- Basic Range
- Multiple Ranges
- Range Customization
- Temperature Gauge with Ranges
- Multiple Axes and Pointers
- Dual-Axis Gauge
- Multiple Pointers on Same Axis
- Multi-Pointer Dashboard
- Common Patterns
- Troubleshooting
---
Axis Customization
Line Style
Customize the axis line (the circular track) with width and color:
<AxisDirective
lineStyle={{
width: 2,
color: '#e0e0e0'
}}
/>Axis Background
Add a background color or pattern to the axis area:
<AxisDirective
background='rgba(200, 220, 240, 0.3)'
/>Complete Axis Styling Example
<AxisDirective
lineStyle={{
width: 3,
color: '#1976d2'
}}
background='rgba(25, 118, 210, 0.1)'
majorTicks={{
interval: 10,
width: 2,
color: '#1976d2',
offset: 5
}}
minorTicks={{
interval: 2,
width: 1,
color: '#90caf9',
offset: 5
}}
labelStyle={{
color: '#1976d2',
offset: 15,
format: '{value}%'
}}
/>---
Axis Angles and Direction
Start and End Angles
By default, the gauge sweeps from 200° to 160° (semi-circular). Customize with startAngle and endAngle:
// Semicircular (bottom half)
<AxisDirective
startAngle={180}
endAngle={0}
/>
// Full circle
<AxisDirective
startAngle={0}
endAngle={360}
/>
// Quarter circle (top-right)
<AxisDirective
startAngle={270}
endAngle={0}
/>
// Speedometer style (bottom-left to top-right)
<AxisDirective
startAngle={270}
endAngle={90}
/>Angle reference:
- 0° = Right (3 o'clock)
- 90° = Bottom (6 o'clock)
- 180° = Left (9 o'clock)
- 270° = Top (12 o'clock)
Axis Direction
Control whether the axis sweeps clockwise or counter-clockwise:
// Clockwise (default, values increase going right)
<AxisDirective direction='ClockWise' />
// Counter-clockwise (values increase going left)
<AxisDirective direction='AntiClockWise' />Common Angle Combinations
// Semicircular gauge (bottom to top)
<AxisDirective startAngle={270} endAngle={90} />
// Speedometer (quarter circle)
<AxisDirective startAngle={270} endAngle={0} direction='ClockWise' />
// Temperature gauge (bottom half)
<AxisDirective startAngle={180} endAngle={0} />
// Linear-like gauge (full circle, might show 180° only)
<AxisDirective startAngle={0} endAngle={180} />---
Axis Scale and Labels
Minimum and Maximum Values
Define the scale range:
<AxisDirective
minimum={0}
maximum={100}
/>
// For percentage gauge
<AxisDirective
minimum={0}
maximum={100}
/>
// For temperature (-50 to 50 Celsius)
<AxisDirective
minimum={-50}
maximum={50}
/>
// For speed (0 to 300 km/h)
<AxisDirective
minimum={0}
maximum={300}
/>Major and Minor Ticks
Control tick marks on the axis:
<AxisDirective
majorTicks={{
interval: 20, // Every 20 units
width: 2, // Thickness
color: '#616161', // Color
offset: 5 // Distance from axis
}}
minorTicks={{
interval: 4, // Every 4 units (5 minor between each major)
width: 1,
color: '#9e9e9e',
offset: 5
}}
/>Labels
Format and position the numeric labels:
<AxisDirective
labelStyle={{
position: 'Outside' // 'Inside', 'Outside','Cross'
color: '#424242',
size: '14px',
offset: 15, // Distance from axis line
format: '{value}°C' // Custom format
}}
/>---
Pointer Types
The gauge supports three pointer types for displaying values:
Needle Pointer (Default)
Classic needle/hand indicator, ideal for speedometers:
<PointerDirective
type='Needle'
value={75}
/>Needle-specific properties:
radius- Length of the needle (50%, 80%, etc.)pointerWidth- Width of the needle lineneedleTail- Configuration object for tail:length- Tail length (20%, 30%, etc.)color- Tail colorcap- Configuration object for center cap:radius- Cap radiuscolor- Cap colorborder- Border configuration
RangeBar Pointer
Filled bar from center to value, ideal for progress indicators:
<PointerDirective value={60} type="RangeBar" radius="80%" pointerWidth={10} color="#4caf50" roundedCorners={true} />RangeBar-specific properties:
radius- Length from center (50%, 80%, etc.)pointerWidth- Bar thicknesscolor- Bar fill colorroundedCorners- Round the bar ends (boolean)
Marker Pointer
Symbol at the value position, ideal for multi-pointer displays:
<PointerDirective value={45} type="Marker" markerShape="Circle" markerWidth={20} markerHeight={20} offset={10} color="#f44336" />Marker-specific properties:
markerShape- Shape typemarkerWidth- Marker size (20, 30, etc.)markerHeight- Marker heightimageUrl- URL for Image marker typeradius- Distance from center where marker is positioned (50%, 80%, etc.)
---
Needle Pointer
Basic Needle Configuration
<PointerDirective
value={85}
type='Needle'
radius='80%'
pointerWidth={5}
color='#424242'
/>Needle with Cap and Tail
<PointerDirective
value={85}
type='Needle'
radius='80%'
pointerWidth={6}
color='#1976d2'
cap={{
radius: 10,
color: '#1976d2',
border: {
width: 3,
color: '#ffffff'
}
}}
needleTail={{
length: '25%',
width: 4,
color: '#1976d2'
}}
/>Styled Speedometer Needle
<PointerDirective
value={60}
type='Needle'
radius='75%'
pointerWidth={4}
color='#f57c00'
animation={{
duration: 500,
enable: true
}}
cap={{
radius: 12,
color: '#f57c00',
border: {
width: 2,
color: '#ffd54f'
}
}}
needleTail={{
length: '20%',
width: 3,
color: '#f57c00'
}}
/>---
RangeBar Pointer
Basic RangeBar
<PointerDirective
value={65}
type='RangeBar'
radius='80%'
pointerWidth={12}
color='#4caf50'
/>RangeBar with Rounded Corners
<PointerDirective
value={70}
type='RangeBar'
radius='75%'
pointerWidth={15}
color='#2196f3'
roundedCorners={true}
/>Multiple RangeBars (Progress Layers)
<PointersDirective>
{/* Background bar */}
<PointerDirective
value={100}
type='RangeBar'
radius='60%'
pointerWidth={20}
color='#e0e0e0'
/>
{/* Actual progress */}
<PointerDirective
value={75}
type='RangeBar'
radius='60%'
pointerWidth={20}
color='#4caf50'
/>
</PointersDirective>---
Marker Pointer
Basic Marker
<PointerDirective
value={50}
type='Marker'
markerShape='Circle'
/>Different Marker Shapes
<PointersDirective>
<PointerDirective value={20} type='Marker' markerShape='Circle' />
<PointerDirective value={40} type='Marker' markerShape='Rectangle' />
<PointerDirective value={60} type='Marker' markerShape='Triangle' />
<PointerDirective value={80} type='Marker' markerShape='Diamond' />
</PointersDirective>Custom Marker with Image
<PointerDirective
value={75}
type='Marker'
markerShape='Image'
imageUrl='./assets/arrow.png'
markerWidth={30}
markerHeight={40}
/>Styled Marker
<PointerDirective
value={50}
type='Marker'
markerShape='Circle'
markerWidth={20}
markerHeight={20}
color='#ff6f00'
radius='85%'
/>---
Ranges
Ranges define colored segments on the axis background to indicate value zones:
Basic Range
<RangeDirective
start={0}
end={30}
color='#4caf50'
/>Multiple Ranges
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
RangesDirective,
RangeDirective,
} from '@syncfusion/ej2-react-circulargauge';
export function App() {
return (
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective>
<RangesDirective>
<RangeDirective
start={0}
end={33}
color="#4caf50"
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={33}
end={66}
color="#fbc02d"
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={66}
end={100}
color="#f44336"
startWidth={10}
endWidth={10}
/>
</RangesDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);
Range Customization
<RangeDirective
start={40}
end={80}
color='#2196f3'
startWidth={5} // Width at start point
endWidth={10} // Width at end point (tapered)
opacity={0.8} // Transparency (0-1)
roundedCorners={true}
/>Temperature Gauge with Ranges
<RangesDirective>
{/* Cold (blue) */}
<RangeDirective start={-50} end={0} color='#2196f3' startWidth={12} endWidth={12} />
{/* Moderate (green) */}
<RangeDirective start={0} end={30} color='#4caf50' startWidth={12} endWidth={12} />
{/* Warm (orange) */}
<RangeDirective start={30} end={40} color='#ff9800' startWidth={12} endWidth={12} />
{/* Hot (red) */}
<RangeDirective start={40} end={50} color='#f44336' startWidth={12} endWidth={12} />
</RangesDirective>---
Multiple Axes and Pointers
Dual-Axis Gauge
Display two independent scales:
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective,
} from '@syncfusion/ej2-react-circulargauge';
export function RealtimeDashboard() {
return (
<div style={{ height: '500px', width: '100%' }}>
<CircularGaugeComponent>
<AxesDirective>
{/* First axis (Celsius) */}
<AxisDirective
minimum={0}
maximum={50}
lineStyle={{ color: '#2196f3' }}
labelStyle={{ format: '{value}°C' }}
>
<PointersDirective>
<PointerDirective value={25} color="#2196f3" />
</PointersDirective>
</AxisDirective>
{/* Second axis (Fahrenheit) */}
<AxisDirective
minimum={32}
maximum={122}
lineStyle={{ color: '#f44336' }}
labelStyle={{ format: '{value}°F' }}
>
<PointersDirective>
<PointerDirective value={77} color="#f44336" />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
// Mounting
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeDashboard />);
Multiple Pointers on Same Axis
Compare different values:
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective
} from '@syncfusion/ej2-react-circulargauge';
export function RealtimeDashboard() {
return (
<div style={{ height: '500px', width: '100%' }}>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective>
<PointersDirective>
<PointerDirective value={30} type="Needle" color="#1976d2" />
<PointerDirective
value={50}
type="Marker"
markerShape="Circle"
color="#f44336"
/>
<PointerDirective value={70} type="RangeBar" color="#4caf50" />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
// Mounting
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeDashboard />);
Multi-Pointer Dashboard
Combine multiple axes for complex monitoring:
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective,
RangesDirective,
RangeDirective,
} from '@syncfusion/ej2-react-circulargauge';
export function RealtimeDashboard() {
return (
<div style={{ height: '500px', width: '100%' }}>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<PointersDirective>
<PointerDirective value={60} type="Needle" color="#1976d2" />
<PointerDirective value={75} type="Marker" color="#f44336" />
</PointersDirective>
</AxisDirective>
<AxisDirective minimum={0} maximum={200}>
<PointersDirective>
<PointerDirective value={120} type="RangeBar" color="#4caf50" />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
// Mounting
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeDashboard />);
---
Common Patterns
Speedometer
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective,
RangesDirective,
RangeDirective
} from '@syncfusion/ej2-react-circulargauge';
export function RealtimeDashboard() {
return (
<div style={{ height: '500px', width: '100%' }}>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective
startAngle={270}
endAngle={90}
minimum={0}
maximum={240}
>
<RangesDirective>
<RangeDirective start={0} end={80} color="#4caf50" startWidth={10} endWidth={10} />
<RangeDirective start={80} end={160} color="#fbc02d" startWidth={10} endWidth={10} />
<RangeDirective start={160} end={240} color="#f44336" startWidth={10} endWidth={10} />
</RangesDirective>
<PointersDirective>
<PointerDirective value={120} radius="80%" />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
// Mounting
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeDashboard />);Progress/Percentage
import React from 'react';
import { createRoot } from 'react-dom/client';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective,
RangesDirective,
RangeDirective,
} from '@syncfusion/ej2-react-circulargauge';
export function RealtimeDashboard() {
return (
<div style={{ height: '500px', width: '100%' }}>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective
startAngle={270}
endAngle={90}
minimum={0}
maximum={100}
>
<RangesDirective>
<RangeDirective
start={0}
end={100}
color="#e0e0e0"
startWidth={15}
endWidth={15}
/>
</RangesDirective>
<PointersDirective>
<PointerDirective value={65} type="RangeBar" color="#4caf50" />
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
// Mounting
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeDashboard />);
---
Troubleshooting
Pointer not visible: Check that pointer value is within axis minimum/maximum range.
Range colors not showing: Ensure range start/end values are within axis scale.
Multiple pointers overlapping: Use different pointer types or adjust radius values.
Common Patterns & Use Cases
Refer to the API quick guide: api-reference.md for exact prop, method and directive names used in these patterns.
Table of Contents
- Speedometer Pattern
- Progress/Percentage Gauge
- Temperature Gauge
- Multi-Pointer Comparison
- Real-Time Monitoring Dashboard
- Performance Troubleshooting
- Gauge Renders Slowly
- Multiple Gauges Cause Performance Issues
- Large Ranges or Pointers Overlap
- Export/Print Produces Blurry Output
- Accessibility Best Practices
- Performance Tips
---
Speedometer Pattern
Classic speedometer showing speed with colored zones:
import * as React from "react";
import { createRoot } from 'react-dom/client';
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective, RangesDirective, RangeDirective,
AnnotationsDirective, AnnotationDirective }
from '@syncfusion/ej2-react-circulargauge';
export function App() {
const [speed, setSpeed] = React.useState(60);
return (
<div style={{ height: '600px' }}>
<CircularGaugeComponent
title="Speedometer"
titleStyle={{ size: '22px', color: '#424242' }}
>
<AxesDirective>
<AxisDirective
startAngle={270}
endAngle={90}
minimum={0}
maximum={240}
lineStyle={{ width: 2, color: '#e0e0e0' }}
majorTicks={{
interval: 20,
width: 2,
color: '#616161',
offset: 5
}}
minorTicks={{
interval: 4,
width: 1,
color: '#9e9e9e',
offset: 5
}}
labelStyle={{
color: '#616161',
offset: 15,
format: '{value}'
}}
>
<RangesDirective>
<RangeDirective
start={0}
end={80}
color='#4caf50'
startWidth={12}
endWidth={12}
label='Safe'
/>
<RangeDirective
start={80}
end={160}
color='#fbc02d'
startWidth={12}
endWidth={12}
label='Caution'
/>
<RangeDirective
start={160}
end={240}
color='#f44336'
startWidth={12}
endWidth={12}
label='Danger'
/>
</RangesDirective>
<PointersDirective>
<PointerDirective
value={speed}
type='Needle'
radius='80%'
pointerWidth={5}
color='#424242'
animation={{
enable: true,
duration: 300
}}
cap={{
radius: 10,
color: '#424242',
border: {
color: '#ffffff',
width: 2
}
}}
needleTail={{
length: '20%',
color: '#424242'
}}
/>
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content={`${Math.round(speed)} km/h`}
radius="0%"
angle={0}
textStyle={{
size: '24px',
fontWeight: 'bold',
color: '#1976d2'
}}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
<div style={{ marginTop: '20px' }}>
<input
type="range"
min="0"
max="240"
value={speed}
onChange={(e) => setSpeed(Number(e.target.value))}
style={{ width: '100%' }}
/>
</div>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<App />);---
Progress/Percentage Gauge
Circular progress indicator showing completion percentage:
eimport * as React from "react";
import { createRoot } from 'react-dom/client';
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective, RangesDirective, RangeDirective,
AnnotationsDirective, AnnotationDirective }
from '@syncfusion/ej2-react-circulargauge';
export function ProgressGauge() {
const [progress, setProgress] = React.useState(65);
return (
<div style={{ height: '400px' }}>
<CircularGaugeComponent
title="Project Progress"
titleStyle={{ size: '18px' }}
background='#f5f5f5'
>
<AxesDirective>
<AxisDirective
startAngle={270}
endAngle={90}
minimum={0}
maximum={100}
lineStyle={{ width: 0 }} // No axis line
majorTicks={{ interval: 0 }} // No ticks
minorTicks={{ interval: 0 }}
labelStyle={{ size: '0px' }} // No labels
>
<RangesDirective>
{/* Background range */}
<RangeDirective
start={0}
end={100}
color='#e0e0e0'
startWidth={20}
endWidth={20}
/>
{/* Progress range */}
<RangeDirective
start={0}
end={progress}
color='#4caf50'
startWidth={20}
endWidth={20}
/>
</RangesDirective>
<PointersDirective>
<PointerDirective
value={0} // Don't show pointer
type='Needle'
radius='0%'
/>
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content={`${progress}%`}
radius="0%"
textStyle={{
size: '36px',
fontWeight: 'bold',
color: '#1976d2'
}}
/>
<AnnotationDirective
content="Complete"
radius="0%"
angle={90}
textStyle={{
size: '14px',
color: '#757575'
}}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<ProgressGauge />);---
Temperature Gauge
Monitor temperature with intuitive color zones:
import * as React from "react";
import { createRoot } from 'react-dom/client';
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective, RangesDirective, RangeDirective,
AnnotationsDirective, AnnotationDirective }
from '@syncfusion/ej2-react-circulargauge';
export function TemperatureGauge() {
const [temperature, setTemperature] = React.useState(22);
const getStatus = () => {
if (temperature < 0) return 'Frozen';
if (temperature < 15) return 'Cold';
if (temperature < 25) return 'Comfortable';
if (temperature < 35) return 'Warm';
return 'Hot';
};
return (
<div style={{ height: '500px' }}>
<CircularGaugeComponent
title="Temperature Monitor"
>
<AxesDirective>
<AxisDirective
minimum={-50}
maximum={50}
startAngle={270}
endAngle={90}
lineStyle={{ width: 2, color: '#90caf9' }}
labelStyle={{
format: '{value}°C',
color: '#1976d2'
}}
majorTicks={{
interval: 10,
color: '#1976d2'
}}
>
<RangesDirective>
<RangeDirective
start={-50}
end={0}
color='#2196f3'
startWidth={15}
endWidth={15}
label='Below 0°C'
/>
<RangeDirective
start={0}
end={15}
color='#4caf50'
startWidth={15}
endWidth={15}
label='Cold'
/>
<RangeDirective
start={15}
end={25}
color='#8bc34a'
startWidth={15}
endWidth={15}
label='Comfort'
/>
<RangeDirective
start={25}
end={35}
color='#ff9800'
startWidth={15}
endWidth={15}
label='Warm'
/>
<RangeDirective
start={35}
end={50}
color='#f44336'
startWidth={15}
endWidth={15}
label='Hot'
/>
</RangesDirective>
<PointersDirective>
<PointerDirective
value={temperature}
type='Needle'
radius='80%'
color='#616161'
animation={{ enable: true, duration: 500 }}
/>
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content={`${temperature}°C`}
radius="0%"
textStyle={{ size: '28px', fontWeight: 'bold' }}
/>
<AnnotationDirective
content={getStatus()}
radius="0%"
angle={90}
textStyle={{ size: '16px', color: '#757575' }}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
<div style={{ marginTop: '20px' }}>
<input
type="range"
min="-50"
max="50"
value={temperature}
onChange={(e) => setTemperature(Number(e.target.value))}
style={{ width: '100%' }}
/>
</div>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<TemperatureGauge />);---
Multi-Pointer Comparison
Compare multiple values on same gauge:
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import React from 'react';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective,
RangesDirective,
RangeDirective,
AnnotationsDirective,
AnnotationDirective,
} from '@syncfusion/ej2-react-circulargauge';
export function MultiPointerGauge() {
return (
<div style={{ height: '500px' }}>
<CircularGaugeComponent title="Performance Comparison">
<AxesDirective>
<AxisDirective
minimum={0}
maximum={100}
startAngle={270}
endAngle={90}
>
<RangesDirective>
<RangeDirective
start={0}
end={30}
color="#4caf50"
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={30}
end={60}
color="#fbc02d"
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={60}
end={100}
color="#f44336"
startWidth={10}
endWidth={10}
/>
</RangesDirective>
<PointersDirective>
{/* Target/Goal */}
<PointerDirective
value={80}
type="Marker"
markerShape="Circle"
markerWidth={16}
markerHeight={16}
color="#1976d2"
radius="85%"
/>
{/* Actual */}
<PointerDirective
value={65}
type="Needle"
radius="80%"
color="#f44336"
/>
{/* Forecast */}
<PointerDirective
value={72}
type="Marker"
markerShape="Triangle"
markerWidth={14}
markerHeight={14}
color="#ff9800"
radius="75%"
/>
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content="Legend:"
radius="120%"
angle={270}
textStyle={{ size: '12px' }}
/>
<AnnotationDirective
content="● Actual: 65%"
radius="120%"
angle={260}
textStyle={{ size: '11px', color: '#f44336' }}
/>
<AnnotationDirective
content="● Target: 80%"
radius="120%"
angle={250}
textStyle={{ size: '11px', color: '#1976d2' }}
/>
<AnnotationDirective
content="▲ Forecast: 72%"
radius="120%"
angle={240}
textStyle={{ size: '11px', color: '#ff9800' }}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<MultiPointerGauge />);
---
Real-Time Monitoring Dashboard
Complete dashboard with multiple real-time gauges:
import * as React from 'react';
import { createRoot } from 'react-dom/client';
import React from 'react';
import {
CircularGaugeComponent,
AxesDirective,
AxisDirective,
PointersDirective,
PointerDirective,
RangesDirective,
RangeDirective,
AnnotationsDirective,
AnnotationDirective,
} from '@syncfusion/ej2-react-circulargauge';
import React, { useState, useEffect } from 'react';
export function RealtimeDashboard() {
const [metrics, setMetrics] = useState({
cpu: 45,
memory: 60,
disk: 75,
network: 30,
});
useEffect(() => {
const interval = setInterval(() => {
setMetrics({
cpu: Math.max(0, Math.min(100, 40 + Math.random() * 60)),
memory: Math.max(0, Math.min(100, 45 + Math.random() * 50)),
disk: Math.max(0, Math.min(100, 70 + Math.random() * 20)),
network: Math.max(0, Math.min(100, 20 + Math.random() * 60)),
});
}, 2000);
return () => clearInterval(interval);
}, []);
const MetricGauge = ({ title, value, unit }) => (
<div style={{ height: '350px', padding: '10px' }}>
<CircularGaugeComponent title={title}>
<AxesDirective>
<AxisDirective minimum={0} maximum={100}>
<RangesDirective>
<RangeDirective
start={0}
end={30}
color="#4caf50"
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={30}
end={60}
color="#fbc02d"
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={60}
end={100}
color="#f44336"
startWidth={10}
endWidth={10}
/>
</RangesDirective>
<PointersDirective>
<PointerDirective
value={value}
animation={{ enable: true, duration: 500 }}
/>
</PointersDirective>
<AnnotationsDirective>
<AnnotationDirective
content={`${value.toFixed(1)}${unit}`}
radius="0%"
textStyle={{ size: '22px', fontWeight: 'bold' }}
/>
</AnnotationsDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
return (
<div
style={{
display: 'grid',
gridTemplateColumns: 'repeat(auto-fit, minmax(300px, 1fr))',
gap: '10px',
padding: '20px',
backgroundColor: '#fafafa',
}}
>
<MetricGauge title="CPU Usage" value={metrics.cpu} unit="%" />
<MetricGauge title="Memory Usage" value={metrics.memory} unit="%" />
<MetricGauge title="Disk Usage" value={metrics.disk} unit="%" />
<MetricGauge title="Network" value={metrics.network} unit="%" />
</div>
);
}
const root = createRoot(document.getElementById('container'));
root.render(<RealtimeDashboard />);
---
Performance Troubleshooting
Common Issues and Solutions
Issue: Gauge Renders Slowly with Real-Time Updates
Cause: Frequent re-renders with unnecessary animations
Solution: Throttle updates and use shouldComponentUpdate:
import React, { useState, useEffect, useCallback } from 'react';
export function OptimizedGauge() {
const [value, setValue] = useState(50);
const [lastUpdate, setLastUpdate] = useState(Date.now());
useEffect(() => {
const interval = setInterval(() => {
const now = Date.now();
// Only update if 500ms has passed
if (now - lastUpdate > 500) {
setValue(Math.random() * 100);
setLastUpdate(now);
}
}, 500);
return () => clearInterval(interval);
}, [lastUpdate]);
return (
<CircularGaugeComponent>
{/* gauge with optimized updates */}
</CircularGaugeComponent>
);
}Issue: Multiple Gauges Cause Performance Issues
Solution: Lazy load or virtualize gauges:
import React, { useState, lazy, Suspense } from 'react';
const GaugeComponent = lazy(() =>
Promise.resolve({ default: () => <CircularGaugeComponent>{/* */}</CircularGaugeComponent> })
);
export function EfficientDashboard() {
const [visibleGauges, setVisibleGauges] = useState([0, 1]);
return (
<div>
{visibleGauges.map((index) => (
<Suspense key={index} fallback={<div>Loading...</div>}>
<GaugeComponent />
</Suspense>
))}
</div>
);
}Issue: Large Ranges or Pointers Overlap
Solution: Adjust radius and pointer width:
// Spread out multiple pointers
<PointersDirective>
<PointerDirective value={30} radius="60%" pointerWidth={3} />
<PointerDirective value={50} radius="70%" pointerWidth={3} />
<PointerDirective value={70} radius="80%" pointerWidth={3} />
</PointersDirective>Issue: Export/Print Produces Blurry Output
Solution: Ensure sufficient container size before export:
// Make container larger for export
<div style={{ height: '800px', width: '800px' }}>
<CircularGaugeComponent ref={gaugeRef}>
{/* gauge */}
</CircularGaugeComponent>
</div>
// Then export
gaugeRef.current?.export('PNG', 'gauge.png');---
Accessibility Best Practices
- Add
ariaLabelfor all gauges - Use sufficient color contrast (minimum 4.5:1)
- Test keyboard navigation
- Provide text alternatives for complex visualizations
- Use
aria-livefor real-time updates
---
Performance Tips
- Throttle real-time updates to ~500-1000ms
- Disable animations for frequent updates
- Limit to 4-6 gauges per page
- Use SVG export for printing (better quality)
- Lazy load gauges outside viewport
- Avoid complex HTML in annotations
Getting Started with React Circular Gauge
This guide covers installation, setup, and creating your first Circular Gauge component.
Table of contents
- Installation
- Step 1: Install the Package
- Import CSS Theme
- Project Setup
- Using Vite (Recommended)
- Using Create React App
- Using TypeScript
- Basic Component Initialization
- Minimal Example
- Add a Container Height
- Working Example: Simple Speedometer
- Common Initialization Issues
- Issue: Gauge Not Rendering
- Issue: CSS Not Applied
- Issue: Types Not Found (TypeScript)
- Next Steps
---
Installation
Step 1: Install the Package
npm install @syncfusion/ej2-react-circulargauge --saveThe Circular Gauge package has the following dependencies:
@syncfusion/ej2-react-base@syncfusion/ej2-circulargauge@syncfusion/ej2-base@syncfusion/ej2-svg-base@syncfusion/ej2-paf-export(for print/export)
All dependencies are installed automatically with npm.
Step 2: Theme Customizing
Available themes:
material.css- Material Design theme (default)fabric.css- Fabric themebootstrap.css- Bootstrap themebootstrap4.css- Bootstrap 4 themefluent.css- Fluent Design themehighcontrast.css- High contrast theme
---
Project Setup
Using Vite (Recommended)
Vite provides faster development with optimized builds.
# Create new project
npm create vite@latest my-gauge-app -- --template react-ts
# Install dependencies
cd my-gauge-app
npm install
# Install Circular Gauge
npm install @syncfusion/ej2-react-circulargauge --save
# Start dev server
npm run devUsing Create React App
# Create new project
npx create-react-app my-gauge-app
# Install dependencies
cd my-gauge-app
# Install Circular Gauge
npm install @syncfusion/ej2-react-circulargauge --save
# Start dev server
npm startUsing TypeScript
Both Vite and CRA support TypeScript. For Vite:
npm create vite@latest my-gauge-app -- --template react-tsThis provides TypeScript support with proper type definitions for Syncfusion components.
---
Basic Component Initialization
Minimal Example
The simplest working Circular Gauge requires the component wrapper and at least one axis:
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective }
from '@syncfusion/ej2-react-circulargauge';
export function App() {
return (
<div style={{ height: '500px' }}>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective />
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
export default App;This renders a default circular gauge with:
- Start angle: 200°
- End angle: 160°
- Minimum value: 0
- Maximum value: 100
- Default pointer at value 0
Add a Container Height
Always wrap the gauge in a container with a defined height:
<div style={{ height: '500px', width: '100%' }}>
<CircularGaugeComponent>
{/* gauge content */}
</CircularGaugeComponent>
</div>Without a height, the gauge may not render correctly.
---
Working Example: Simple Speedometer
Here's a complete working example with installation steps:
import React from 'react';
import { CircularGaugeComponent, AxesDirective, AxisDirective,
PointersDirective, PointerDirective, RangesDirective, RangeDirective }
from '@syncfusion/ej2-react-circulargauge';
export function App() {
return (
<div style={{ height: '600px', width: '100%' }}>
<CircularGaugeComponent
title="Speed (km/h)"
titleStyle={{
size: '20px',
color: '#424242'
}}
centerX="50%"
centerY="50%"
>
<AxesDirective>
<AxisDirective
minimum={0}
maximum={240}
startAngle={270}
endAngle={90}
lineStyle={{ width: 2, color: '#E0E0E0' }}
majorTicks={{
interval: 20,
width: 2,
color: '#616161'
}}
minorTicks={{
interval: 4,
width: 1,
color: '#9E9E9E'
}}
labelStyle={{
color: '#616161',
offset: 15
}}
>
{/* Define colored ranges */}
<RangesDirective>
<RangeDirective
start={0}
end={60}
color='#30B32D'
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={60}
end={120}
color='#FFDD00'
startWidth={10}
endWidth={10}
/>
<RangeDirective
start={120}
end={240}
color='#F03E3E'
startWidth={10}
endWidth={10}
/>
</RangesDirective>
{/* Add pointer */}
<PointersDirective>
<PointerDirective
value={85}
type='Needle'
radius='80%'
pointerWidth={5}
color='#424242'
cap={{
radius: 8,
color: '#424242',
border: {
color: '#ffffff',
width: 2
}
}}
needleTail={{
length: '20%',
color: '#424242'
}}
/>
</PointersDirective>
</AxisDirective>
</AxesDirective>
</CircularGaugeComponent>
</div>
);
}
export default App;Installation steps: 1. Create React app: npm create vite@latest my-app -- --template react-ts 2. Install gauge: npm install @syncfusion/ej2-react-circulargauge --save 3. Copy the code above into src/App.tsx 4. Run: npm run dev 5. Open browser to http://localhost:5173
---
Common Initialization Issues
Issue: Gauge Not Rendering
Cause: Missing container height
// ❌ Wrong
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective />
</AxesDirective>
</CircularGaugeComponent>
// ✅ Correct
<div style={{ height: '500px' }}>
<CircularGaugeComponent>
<AxesDirective>
<AxisDirective />
</AxesDirective>
</CircularGaugeComponent>
</div>Issue: Types Not Found (TypeScript)
Cause: Missing type definitions
# Types are included in the package, but ensure proper TypeScript setup
npm install --save-dev typescript @types/react @types/node---
Next Steps
Also review the API reference: api-reference.md
Once you have the basic gauge working:
1. Configure axes and pointers → See axes-pointers-ranges.md 2. Customize appearance → See appearance-dimensions.md 3. Add interactions → See advanced-features.md 4. View common patterns → See common-patterns.md