Angular Responsive HTML Annotations Example

Demonstrates how to use the HtmlCustomAnnotation to create responsive text content using SciChart.js, High Performance JavaScript Charts

Fullscreen

Edit

 Edit

Docs

drawExample.ts

angular.ts

theme.ts

Copy to clipboard
Minimise
Fullscreen
1import {
2    HtmlCustomAnnotation,
3    CategoryAxis,
4    EAnnotationLayer,
5    ECoordinateMode,
6    EHorizontalAnchorPoint,
7    EVerticalAnchorPoint,
8    EXyDirection,
9    MouseWheelZoomModifier,
10    NumberRange,
11    NumericAxis,
12    SciChartSurface,
13    ZoomPanModifier,
14    SmartDateLabelProvider,
15    AnnotationHoverModifier,
16    HtmlTextAnnotation,
17    AnnotationBase,
18    easing,
19    EHoverMode,
20    GenericAnimation,
21    translateFromCanvasToSeriesViewRect,
22    translateToNotScaled,
23    IAnnotation,
24} from "scichart";
25
26import "./styles.css";
27import { appTheme } from "../../../theme";
28
29const data1 = [
30    {
31        start: 1745830800,
32        end: 1745834400,
33        title: "Standup Meeting",
34        color: "#FF6B6B",
35    },
36    {
37        start: 1745834400,
38        end: 1745838900,
39        title: "Planning Session",
40        color: "#4ECDC4",
41    },
42    {
43        start: 1745838900,
44        end: 1745842500,
45        title: "Lunch Break",
46        color: "#FFD93D",
47    },
48    {
49        start: 1745842500,
50        end: 1745847900,
51        title: "Presentation Prep",
52        color: "#1A535C",
53    },
54    {
55        start: 1745847900,
56        end: 1745851500,
57        title: "One-on-One Meeting",
58        color: "#FF9F1C",
59    },
60    {
61        start: 1745851500,
62        end: 1745855100,
63        title: "Email Responses",
64        color: "#6A4C93",
65    },
66];
67
68const data2 = [
69    {
70        start: 1745830800,
71        end: 1745832600,
72        title: "Morning Sync",
73        color: "#FFB5E8",
74    },
75    {
76        start: 1745832600,
77        end: 1745836200,
78        title: "Design Review",
79        color: "#B5EAD7",
80    },
81    {
82        start: 1745836200,
83        end: 1745839800,
84        title: "Code Implementation",
85        color: "#C7CEEA",
86    },
87    {
88        start: 1745839800,
89        end: 1745843400,
90        title: "Lunch + Walk",
91        color: "#FFDAC1",
92    },
93    {
94        start: 1745843400,
95        end: 1745848800,
96        title: "Dev Handoff",
97        color: "#E2F0CB",
98    },
99    {
100        start: 1745848800,
101        end: 1745855100,
102        title: "Documentation",
103        color: "#FFABAB",
104    },
105];
106
107const data3 = [
108    {
109        start: 1745830800,
110        end: 1745833500,
111        title: "Daily Briefing",
112        color: "#FFD6A5",
113    },
114    {
115        start: 1745833500,
116        end: 1745838000,
117        title: "UX Interviews",
118        color: "#9BF6FF",
119    },
120    {
121        start: 1745838000,
122        end: 1745842500,
123        title: "Lunch & Networking",
124        color: "#A0C4FF",
125    },
126    {
127        start: 1745842500,
128        end: 1745846100,
129        title: "Sprint Planning",
130        color: "#BDB2FF",
131    },
132    {
133        start: 1745846100,
134        end: 1745849700,
135        title: "Code Review",
136        color: "#FFC6FF",
137    },
138    {
139        start: 1745849700,
140        end: 1745855100,
141        title: "Backlog Grooming",
142        color: "#FFFFD1",
143    },
144];
145
146const data4 = [
147    {
148        start: 1745830800,
149        end: 1745834100,
150        title: "System Check-In",
151        color: "#FFADAD",
152    },
153    {
154        start: 1745834100,
155        end: 1745837700,
156        title: "Architecture Planning",
157        color: "#FFD6A5",
158    },
159    {
160        start: 1745837700,
161        end: 1745842200,
162        title: "Lunch Break",
163        color: "#FDFFB6",
164    },
165    {
166        start: 1745842200,
167        end: 1745846700,
168        title: "Testing Session",
169        color: "#CAFFBF",
170    },
171    {
172        start: 1745846700,
173        end: 1745851200,
174        title: "QA Sync",
175        color: "#9BF6FF",
176    },
177    {
178        start: 1745851200,
179        end: 1745855100,
180        title: "End-of-Day Recap",
181        color: "#A0C4FF",
182    },
183];
184
185export const drawExample = async (rootElement: string | HTMLDivElement) => {
186    const { sciChartSurface, wasmContext } = await SciChartSurface.create(rootElement);
187    const xAxis = new CategoryAxis(wasmContext, {
188        isInnerAxis: true,
189        labelStyle: {
190            color: "black",
191            fontSize: 12,
192        },
193        majorGridLineStyle: {
194            color: "gray",
195            strokeDashArray: [2, 2],
196        },
197        drawMinorGridLines: false,
198        drawMajorBands: false,
199        labelProvider: new SmartDateLabelProvider({ rotation: -90 }),
200        visibleRangeLimit: new NumberRange(data1[0].start - 4 * 24 * 60, data1[data1.length - 1].end + 4 * 24 * 60),
201        visibleRange: new NumberRange(data1[0].start, data1[data1.length - 1].end),
202    });
203    const yAxis = new NumericAxis(wasmContext, { isVisible: false });
204
205    sciChartSurface.xAxes.add(xAxis);
206    sciChartSurface.yAxes.add(yAxis);
207
208    sciChartSurface.chartModifiers.add(
209        new ZoomPanModifier({ xyDirection: EXyDirection.XDirection }),
210        new MouseWheelZoomModifier({ xyDirection: EXyDirection.XDirection })
211    );
212
213    const crateTimeSlotAnnotation =
214        (offset: number) =>
215        ({ start, end, title, color }: any) => {
216            const textAnnotation = new HtmlCustomAnnotation({
217                // move to the background to allow drawing grid lines and labels above the annotations
218                annotationLayer: EAnnotationLayer.Background,
219                yCoordinateMode: ECoordinateMode.Relative,
220                x1: start,
221                y1: offset * 0.25,
222                x2: end,
223                y2: (offset + 1) * 0.25,
224                horizontalAnchorPoint: EHorizontalAnchorPoint.Center,
225                verticalAnchorPoint: EVerticalAnchorPoint.Center,
226            });
227
228            textAnnotation.htmlElement.innerHTML = `<div class="responsiveTextAnnotation">${title}</div>`;
229            textAnnotation.htmlElement.classList.add("responsiveTextAnnotationContainer");
230            textAnnotation.htmlElement.style.background = color;
231            return textAnnotation;
232        };
233
234    const annotations1 = data1.map(crateTimeSlotAnnotation(0));
235    const annotations2 = data2.map(crateTimeSlotAnnotation(1));
236    const annotations3 = data3.map(crateTimeSlotAnnotation(2));
237    const annotations4 = data4.map(crateTimeSlotAnnotation(3));
238
239    const titleAnnotation1 = addLaneTitleAnnotation("Employee1", "#FFB6C1", 0);
240    const titleAnnotation2 = addLaneTitleAnnotation("Employee2", "#40E0D0", 0.25);
241    const titleAnnotation3 = addLaneTitleAnnotation("Employee3", "#6A5ACD", 0.5);
242    const titleAnnotation4 = addLaneTitleAnnotation("Employee4", "#ADFF2F", 0.75);
243
244    sciChartSurface.annotations.add(
245        ...annotations1,
246        ...annotations2,
247        ...annotations3,
248        ...annotations4,
249        titleAnnotation1,
250        titleAnnotation2,
251        titleAnnotation3,
252        titleAnnotation4
253    );
254
255    addTooltipForAnnotations(sciChartSurface, [...annotations1, ...annotations2, ...annotations3, ...annotations4]);
256
257    return { sciChartSurface };
258};
259
260function addLaneTitleAnnotation(text: string, background: string, yOffset: number) {
261    return new HtmlTextAnnotation({
262        x1: 0,
263        y1: yOffset,
264        xCoordinateMode: ECoordinateMode.Relative,
265        yCoordinateMode: ECoordinateMode.Relative,
266        horizontalAnchorPoint: EHorizontalAnchorPoint.Left,
267        verticalAnchorPoint: EVerticalAnchorPoint.Top,
268        textContainerStyle: {
269            fontSize: "10px",
270            color: "black",
271            opacity: "0.7",
272            background,
273        },
274        text,
275    });
276}
277
278function addTooltipForAnnotations(sciChartSurface: SciChartSurface, targets: IAnnotation[]) {
279    const tooltipAnnotation = new HtmlTextAnnotation({
280        x1: 0,
281        y1: 0,
282        xCoordShift: 20,
283        yCoordShift: 20,
284        xCoordinateMode: ECoordinateMode.Pixel,
285        yCoordinateMode: ECoordinateMode.Pixel,
286        horizontalAnchorPoint: EHorizontalAnchorPoint.Left,
287        verticalAnchorPoint: EVerticalAnchorPoint.Top,
288        textContainerStyle: {
289            fontSize: "12px",
290            color: appTheme.ForegroundColor,
291            padding: "4px",
292            background: "rgba(0, 0, 139, 0.4)",
293            backdropFilter: "blur(10px)",
294            borderRadius: "0px 15px 15px 15px",
295        },
296        text: "",
297        isHidden: true,
298    });
299
300    sciChartSurface.modifierAnnotations.add(tooltipAnnotation);
301
302    let currentTooltipAnimation: GenericAnimation<number>;
303    const animateTooltip = () => {
304        currentTooltipAnimation?.cancel();
305        tooltipAnnotation.isHidden = true;
306        currentTooltipAnimation = new GenericAnimation<number>({
307            from: 0,
308            to: 1,
309            duration: 0,
310            delay: 500,
311            ease: easing.linear,
312            onAnimate: (from: number, to: number, progress) => {},
313            onCompleted: () => {
314                tooltipAnnotation.isHidden = false;
315            },
316        });
317        sciChartSurface.addAnimation(currentTooltipAnimation);
318    };
319
320    const annotationHoverModifier = new AnnotationHoverModifier({
321        // check hover on provided annotations
322        targets,
323        // ignore tooltip annotation if it is overlapping with other
324        hoverMode: EHoverMode.TopmostIncluded,
325        // needed to update tooltip position when moving the cursor within an annotation
326        notifyPositionUpdate: true,
327        // manage tooltip visibility and position
328        onHover: (args) => {
329            const [hoveredAnnotation] = args.hoveredEntities as AnnotationBase[];
330            if (hoveredAnnotation) {
331                if (hoveredAnnotation.isEditable) {
332                    sciChartSurface.domChartRoot.style.cursor = "grab";
333                }
334                if (hoveredAnnotation.isDraggingStarted) {
335                    tooltipAnnotation.isHidden = true;
336                    return;
337                }
338
339                const borders = tooltipAnnotation.getAnnotationBorders(true);
340                tooltipAnnotation.text = `${formatTime(hoveredAnnotation.x1)} - ${formatTime(hoveredAnnotation.x2)}`;
341
342                const handleAnnotationsOutsideSeriesViewRect = true;
343                const translatedMousePoint = translateFromCanvasToSeriesViewRect(
344                    args.mouseArgs.mousePoint,
345                    sciChartSurface.seriesViewRect,
346                    handleAnnotationsOutsideSeriesViewRect
347                );
348                tooltipAnnotation.x1 = translateToNotScaled(translatedMousePoint.x);
349                tooltipAnnotation.y1 = translateToNotScaled(translatedMousePoint.y);
350
351                // initial default offset from pointer
352                tooltipAnnotation.xCoordShift = 20;
353                const width = Math.abs(borders.x2 - borders.x1);
354                const expectedX2Coordinate = tooltipAnnotation.x1 + tooltipAnnotation.xCoordShift + width;
355                const unscaledViewWidth = translateToNotScaled(sciChartSurface.seriesViewRect.width);
356                if (expectedX2Coordinate > unscaledViewWidth) {
357                    tooltipAnnotation.xCoordShift = unscaledViewWidth - width - tooltipAnnotation.x1;
358                }
359
360                animateTooltip();
361            } else {
362                sciChartSurface.domChartRoot.style.cursor = "auto";
363                tooltipAnnotation.isHidden = true;
364                currentTooltipAnimation?.cancel();
365            }
366        },
367    });
368
369    sciChartSurface.chartModifiers.add(annotationHoverModifier);
370}
371
372function formatTime(timestamp: number) {
373    const date = new Date(timestamp * 1000);
374    const hours = date.getHours().toString().padStart(2, "0");
375    const minutes = date.getMinutes().toString().padStart(2, "0");
376    return `${hours}:${minutes}`;
377}
378

Responsive HTML Annotations Example - Angular

Overview

This Angular example illustrates responsive schedule visualization using SciChart's HTML annotations. It demonstrates how to create time-bound annotations with adaptive layouts in an Angular component.

Technical Implementation

The chart is initialized through SciChart Angular component binding. Annotations are configured using HtmlCustomAnnotation with responsive CSS container queries. The implementation includes SmartDateLabelProvider for time formatting and AnnotationHoverModifier for interactive tooltips.

Features and Capabilities

Key features include: adaptive text layout based on container size, interactive time range display, multi-lane schedule organization, and CSS-powered responsive design. The example showcases Angular integration with SciChart's annotation system.

Integration and Best Practices

The implementation follows Angular best practices with standalone components and proper chart lifecycle management. Responsive design is achieved through modern CSS features while maintaining performance with efficient DOM updates.

angular Chart Examples & Demos

See Also: Charts added in v4 (16 Demos)

Angular Histogram Chart | Angular Charts | SciChart.js Demo

Angular Histogram Chart

Create an Angular Histogram Chart with custom texture fills and patterns. Try the SciChartAngular wrapper component for seamless Angular integration today.

Angular Gantt Chart | Angular Charts | SciChart.js Demo

Angular Gantt Chart Example

Build an Angular Gantt Chart with SciChart. View the demo for horizontal bars, rounded corners and data labels to show project timelines and task completion.

Angular Choropleth Map | Angular Charts | SciChart.js Demo

Angular Choropleth Map Example

Create an Angular Choropleth map, a type of thematic map where areas are shaded or patterned in proportion to the value of a variable being represented.

Angular Multi-Layer Map | Angular Charts | SciChart.js Demo

Angular Multi-Layer Map Example

Create a Angular Multi-Layer Map Example, using FastTriangleRenderableSeries with GeoJSON data-points using a constrained delaunay triangulation algorithm.

Angular Animated Bar Chart | Angular Charts | SciChart.js

Angular Animated Bar Chart Example

Bring annual comparison data to life with the Angular Animated Bar Chart example from SciChart. This demo showcases top 10 tennis players from 1990 to 2024.

Angular Vector Field Plot | Angular Charts | SciChart.js Demo

Angular Vector Field Plot

View the Angular Vector Field Plot example from SciChart, including dynamic vector generation, gradient-colored segments, and interactive zoom/pan. Try demo.

Angular Waterfall Chart | Bridge Chart | SciChart.js Demo

Angular Waterfall Chart | Bridge Chart

Build an Angular Waterfall Chart with dynamic coloring, multi-line data labels & responsive design, using ScichartAngular component for seamless integration

Angular Box Plot Chart | Angular Charts | SciChart.js Demo

Angular Box Plot Chart

Try the Angular Box Plot Chart example for Angular-friendly chart lifecycle management, dynamic sub-surface positioning, and custom styling. Try the demo now.

Angular Triangle Series | Triangle Mesh Chart | SciChart

Angular Triangle Series | Triangle Mesh Chart

Create Angular Triangle Meshes with the Triangle Series from SciChart. This demo supports strip mode, list mode and the drawing of polygons. View the example.

Angular Treemap Chart | Angular Charts | SciChart.js Demo

Angular Treemap Chart

Create an Angular Treemap Chart to define rectangle positions based on total value. Use SciChart FastRectangleRenderableSeries and d3-hierarchy.js layouts.

NEW!
Angular Map Chart with Heatmap overlay | SciChart.js Demo

Angular Map Chart with Heatmap overlay

Design a highly dynamic Angular Map Chart with Heatmap overlay with SciChart's feature-rich JavaScript Chart Library. Get your free demo today.

Realtime Audio Analyzer Bars Demo | SciChart.js Demo

Realtime Audio Analyzer Bars Demo

Demonstrating the capability of SciChart.js to create a JavaScript Audio Analyzer Bars and visualize the Fourier-Transform of an audio waveform in realtime.

Angular Linear Gauges | Angular Charts | SciChart.js Demo

Angular Linear Gauges Example

View the Angular Linear Gauge Chart example to combine rectangles & annotations. Create a linear gauge dashboard with animated indicators and custom scales.

NEW!
Angular Order of Rendering | Angular Charts | SciChart.js

Angular Order of Rendering Example

The Angular Order of Rendering example gives you full control of the draw order of series and annotations for charts. Try SciChart's advanced customizations.

HTML Annotations and Custom in-chart Controls | SciChart

HTML Annotations and Custom in-chart Controls Example

Angular HTML Chart Control example demonstrates advanced HTML annotation integration and how to render HTML components within charts. Try the SciChart demo.

Angular Polar Modifiers | Polar Interactivity Modifiers

Angular Polar Modifiers | Polar Interactivity Modifiers Demo

Explore SciChart's Polar Interactivity Modifiers including zooming, panning, and cursor tracking. Try the demo to trial the Polar Chart Behavior Modifiers.

SciChart Ltd, 16 Beaufort Court, Admirals Way, Docklands, London, E14 9XL.