# Viewer Advanced Usage

> HotSpots and annotations in the Viewer.

Source: https://doc.babylonjs.com/features/featuresDeepDive/babylonViewer/advancedUsage

The Babylon Viewer aims to make the most common model viewing scenarios simple and robust. That said, inevitably there will be specific needs for specific use cases, and as such the Babylon Viewer supports several routes for customization.

## Configuring the Babylon Viewer

### `Viewer`
When constructing a low-level `Viewer`, pass in an options object to specify various initialization-time configurations.

### `CreateViewerForCanvas`
Similarly, when calling `CreateViewerForCanvas`, the same options can be passed in.

### `HTML3DElement`
When using the `HTML3DElement` (`<babylon-viewer>`), the same options can again be passed to the constructor. However, an `HTML3DElement` instance is typically created by placing a `<babylon-viewer>` element within an HTML page, so constructor arguments cannot be passed. When it is necessary to provide options for the `HTML3DElement`, use the `ConfigureCustomViewerElement` function to create a custom element with a unique name and the desired options. For example:

```ts
ConfigureCustomViewerElement("my-babylon-viewer", { limitDeviceRatio: 2 });
```

```html
<my-babylon-viewer source="...">
</my-babylon-viewer>
```

In this example, when a `my-babylon-viewer` element is used, it will have a configuration that sets `limitDeviceRatio` to 2, meaning the maximum render resolution will be limited on high-resolution devices with a DPR greater than 2.

## Accessing the full Babylon API through the Viewer's public API

The primary public entry point from the `HTML3DElement` (`<babylon-viewer>`) to the Babylon API is the `viewerDetails` property and the associated `viewerready` event (which fires any time the `viewerDetails` changes). Any time the `HTML3DElement` is disconnected from the DOM, the underlying `viewerDetails` is disposed, and any time it is (re)connected to the DOM, the `viewerDetails` is (re)created. However, it is created asynchronously, so using the `viewerready` event is a way to know when the `engine`, `scene`, etc. have been recreated.

### Example 1 - Drag & Drop

This example uses the `viewerDetails` property to access the underlying `Viewer` and its `loadModel` function to load from a `File` object rather than a URL:

[CodePen: Babylon Viewer Annotations - Custom](https://codepen.io/BabylonJS/pen/VYZjPQQ/)

### Example 2 - Wireframe

This example uses the `modelchange` event and the `viewerDetails` property to access the materials of the loaded model to enable wireframe rendering:

[CodePen: Babylon Viewer Annotations - Custom](https://codepen.io/BabylonJS/pen/mybrWwo/)

## Customizing the Babylon Viewer through the protected API

All layers of the Babylon Viewer support subclassing as a means of customization. Subclasses can access the protected API of each layer.

> [!WARNING]
> The protected API is still experimental and may change in the future.

The low-level `Viewer` exposes many protected APIs and allows multiple models to be loaded simultaneously.

When calling `CreateViewerForCanvas`, it is also possible to pass in a `Viewer` subclass. `CreateViewerForCanvas` will use this subclass when creating the `Viewer` instance.

Similarly, when subclassing `ViewerElement` (the base class of `HTML3DElement`), it is possible to pass in a `Viewer` subclass. Additionally, `ViewerElement` exposes protected APIs that allow for additional customization.

## Further reading

- [Viewer & React](https://doc.babylonjs.com/features/featuresDeepDive/babylonViewer/react)
