Skip to content

Commit cc09f8b

Browse files
feat(widgets): FpsWidget (#9607)
1 parent 7d65052 commit cc09f8b

File tree

5 files changed

+100
-1
lines changed

5 files changed

+100
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# FpsWidget
2+
3+
Displays the measured frames per second (FPS) as reported by the attached
4+
`Deck` instance.
5+
6+
```ts
7+
import {FpsWidget} from '@deck.gl/widgets';
8+
```
9+
10+
## Usage
11+
12+
```ts
13+
new Deck({
14+
widgets: [new FpsWidget({placement: 'top-right'})]
15+
});
16+
```
17+
18+
## Properties
19+
20+
The `FpsWidget` accepts the generic [`WidgetProps`](./overview.md#widgetprops) and
21+
supports one additional option:
22+
23+
### `placement` (String)
24+
25+
- Default: `'top-left'`
26+
- Position of the widget within the view. One of `top-left`, `top-right`, `bottom-left`,
27+
`bottom-right`.
28+

docs/table-of-contents.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@
319319
"api-reference/widgets/fullscreen-widget",
320320
"api-reference/widgets/reset-view-widget",
321321
"api-reference/widgets/screenshot-widget",
322+
"api-reference/widgets/fps-widget",
322323
"api-reference/widgets/loading-widget",
323324
"api-reference/widgets/theme-widget",
324325
"api-reference/widgets/info-widget"

modules/widgets/src/fps-widget.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// deck.gl
2+
// SPDX-License-Identifier: MIT
3+
// Copyright (c) vis.gl contributors
4+
5+
import {Widget, WidgetProps} from '@deck.gl/core';
6+
import type {WidgetPlacement, Deck} from '@deck.gl/core';
7+
8+
/** Properties for the FpsWidget. */
9+
export type FpsWidgetProps = WidgetProps & {
10+
/** Widget positioning within the view. Default 'top-left'. */
11+
placement?: WidgetPlacement;
12+
};
13+
14+
/**
15+
* Displays the average frames per second reported by the Deck instance.
16+
*/
17+
export class FpsWidget extends Widget<FpsWidgetProps> {
18+
static defaultProps: Required<FpsWidgetProps> = {
19+
...Widget.defaultProps,
20+
id: 'fps',
21+
placement: 'top-left'
22+
};
23+
24+
className = 'deck-widget-fps';
25+
placement: WidgetPlacement = 'top-left';
26+
27+
private _lastFps: number = -1;
28+
29+
constructor(props: FpsWidgetProps = {}) {
30+
super(props, FpsWidget.defaultProps);
31+
this.placement = props.placement ?? this.placement;
32+
}
33+
34+
setProps(props: Partial<FpsWidgetProps>): void {
35+
if (props.placement) {
36+
this.placement = props.placement;
37+
}
38+
super.setProps(props);
39+
}
40+
41+
onRenderHTML(rootElement: HTMLElement): void {
42+
const fps = this._getFps();
43+
rootElement.innerText = `FPS:\n${fps}`;
44+
rootElement.style.backgroundColor = 'white';
45+
rootElement.style.fontFamily = 'monospace';
46+
rootElement.style.fontSize = '8px';
47+
rootElement.style.fontWeight = '700'; // Make font bolder on click
48+
}
49+
50+
onRedraw({}: {viewports: any[]; layers: any[]}): void {
51+
const fps = this._getFps();
52+
if (fps !== this._lastFps) {
53+
this._lastFps = fps;
54+
this.updateHTML();
55+
}
56+
}
57+
58+
onAdd({}: {deck: Deck<any>; viewId: string | null}): void {
59+
this._lastFps = this._getFps();
60+
this.updateHTML();
61+
}
62+
63+
_getFps(): number {
64+
// @ts-expect-error protected
65+
return Math.round(this.deck.metrics.fps ?? 0);
66+
}
67+
}

modules/widgets/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ export {GeolocateWidget as _GeolocateWidget} from './geolocate-widget';
1515
export {FullscreenWidget} from './fullscreen-widget';
1616
export {ScreenshotWidget} from './screenshot-widget';
1717
export {LoadingWidget as _LoadingWidget} from './loading-widget';
18+
export {FpsWidget as _FpsWidget} from './fps-widget';
1819
export {ThemeWidget as _ThemeWidget} from './theme-widget';
1920
export {InfoWidget as _InfoWidget} from './info-widget';
2021
export {SplitterWidget as _SplitterWidget} from './splitter-widget';
@@ -28,6 +29,7 @@ export type {ScreenshotWidgetProps} from './screenshot-widget';
2829
export type {ResetViewWidgetProps} from './reset-view-widget';
2930
export type {GeolocateWidgetProps} from './geolocate-widget';
3031
export type {LoadingWidgetProps} from './loading-widget';
32+
export type {FpsWidgetProps} from './fps-widget';
3133
export type {ScaleWidgetProps} from './scale-widget';
3234
export type {ThemeWidgetProps} from './theme-widget';
3335
export type {InfoWidgetProps} from './info-widget';

test/apps/widgets-example-9.2/app.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
_ScaleWidget,
1515
_LoadingWidget,
1616
_ThemeWidget,
17-
_InfoWidget,
17+
_FpsWidget,
1818
_InfoWidget,
1919
_SplitterWidget,
2020
_TimelineWidget,
@@ -98,6 +98,7 @@ const deck = new Deck({
9898
new FullscreenWidget(),
9999
new ScreenshotWidget(),
100100
new ResetViewWidget(),
101+
new _FpsWidget(),
101102
new _LoadingWidget(),
102103
new _ScaleWidget({placement: 'bottom-right'}),
103104
new _GeolocateWidget({viewId: 'left-map'}),

0 commit comments

Comments
 (0)