# Using multiple views

HOOPS Web Viewer 2024.6.0 and above supports multiple views on a single Web Viewer canvas. Common use cases include front, side, and top views, although you are able to set whatever camera your application requires. The number of views is only limited by the capability of the execution environment.

These views can have their own camera, draw mode, lights, and more. In fact, anything that is modified using a call on the `View` class will be unique to that view. All these views share a single `Model` (as well as several other viewer concepts), so any change to the model will be reflected in all views. For example, if you’re viewing a model with two views and move a part, it will move in all views.

There is a new type of key, the `ViewKey` which is an identifier unique to a view. The initial view has a key of `0`. You’re able to add and delete views as needed using functions added to the `WebViewer` class. When creating a new view, you need only supply a `HTMLElement` or a string containing the ID of the `HTMLElement` to set up a new 3D view. Each view is only drawn when it needs to be, so if you’re rotating a camera in one view, the other views will not be drawn.

Once you have created your new view, it will have its own operator stack which allows you to customize interaction.

Important

A user can only create additional views after the `ModelStructureReady` callback has been triggered. Additionally, the initial view cannot be deleted.

Let’s imagine we have a page with two `HTMLElement` containers with IDs of “viewer1” and “viewer2”. To create a new view, simply call `WebViewer.AddView` with the ID of the container:

    <div id="viewer1" class="hwv-view">Initial view</div>
    <div id="viewer2" class="hwv-view">New view</div>

    <script type="module">
    import * as Communicator from "./hoops-web-viewer.mjs";

    // initial view
    const hwv = new Communicator.WebViewer({
            container: "viewer1",
            enginePath: ".",
            endpointUri: "my_model.scs"
    });
    hwv.start();

    hwv.setCallbacks({
            modelStructureReady: () => {
                    // new view
                    hwv.addView({
                            container: "viewer2"
                    });
            }
    });
    </script>

The `class="hwv-view"` is not mandatory - you can use your own styling and layout. In the screenshot below, notice the multiple cameras provide different views, but a selection in one view also selects the same geometry in the second view.

To remove a view, use `WebViewer.removeView`.

A more complete example which shows views being created in response to events can be found at INSTALL_DIR/web_viewer/examples/multi_view.html and its related script INSTALL_DIR/web_viewer/examples/scripts/examples/multi_view.js. This example uses classes to encapsulate the variables and logic, which is recommended for production applications.

## API changes related to this feature

Callbacks

Several callbacks now have an additional `ViewKey` parameter if they happen in a particular view, for example, camera changes. This has been added as the last parameter, so it shouldn’t affect existing callbacks if the user is not interested in multi-view.

Camera

Projection matrices are partially based on the dimensions of the canvas, so an additional, optional `View` parameter has been added to functions that get these matrices. This only affects the default view if it isn’t provided.

Events

Since input events can now potentially happen in a canvas that could differ from the default, they now take a `ViewKey` argument to their constructors. This also applies to keyboard input since we might want to know what view has focus when we press a key.

Model

The `Model` class is largely unaffected. However, CAD views and CAD configurations need to take place in a specific view. So a parameter has been added.

Selection

Since there are multiple cameras now, we need to know which view we’re picking from when we do a screen-based selection. Several selection functions have been changed this way, with an optional `View` parameter at the end. This defaults to the default view if not specified.

Snapshots

`SnapshotConfig` has a optional parameter for a `ViewKey`. This is also able to be set at the end of the constructor.

View

Several managers have been moved from the `WebViewer` to the `View` class since they are more suited to individual views than they are the global viewer. These are `OverlayManager`, `FloorplanManager`, and `OperatorManager`. Each view now has its own operator stack, managed by the `OperatorManager`. Any functions called on the view affect only the view in the canvas they own. So setting lights in one view should do nothing for other views, for example.

WebViewer

As above, the viewer no longer directly manages the `OverlayManager`, `FloorplanManager`, or the `OperatorManager`. These symbols still exist in the `WebViewer` for compatibility, they simply point to the default view’s version of these objects. The `WebViewer` also still has a `view` field which is simply the default view. There are also new functions to `addView`, `removeView`, and `getView`, and a new field `views` which is an array of views.

CallbackMap

The following have an additional ViewKey parameter at the end: + `camera` + `frameDrawn` + `overlayViewportSet` + `transitionBegin` + `transitionEnd` + `viewOrientation`

Camera

The following have an additional optional `View` parameter at the end: + `getProjectionMatrix` + `getFullMatrix`

Event.InputEvent

A constructor and a getter have been added: + `constructor(viewKey: ViewKey)` + `get viewKey(): ViewKey`

Additionally, the following child types are affected by this. They now take a `ViewKey` as the last argument to their constructor:

- `KeyInputEvent`
- `MouseInputEvent`
- `MouseWheelInputEvent`
- `TouchInputEvent`

Model

- `activateCadView` takes an `AbstractView` as its first parameter
- `activateDefaultCadView` takes an `AbstractView` as its first parameter
- `activateCadConfiguration` takes an `AbstractView` as its first parameter
- `activateDefaultCadConfiguration` takes an `AbstractView` as its first parameter

SelectionManager

The following take an optional `View` as their last parameter:

- `selectFromPoint`
- `selectAllFromPoint`
- `selectFromRay`
- `selectAllFromRay`
- `beginScreenSelectByArea`
- `beginRayDrillSelection`

SnapshotConfig

Now has a public `ViewKey` field and in addition the view key can be specified at construction as the last optional parameter.

View

The `View` class now has a `OperatorManager`, `FloorplanManager`, and `OverlayManager` taken from the `WebViewer`. The `WebViewer` version of these symbols simply point to the managers for view `0`.

WebViewer

`view` is now a `get` which returns the default `View`. The `OverlayManager`, `FloorplanManager`, or the `OperatorManager` are all now just getters for those managers on the default view. New functions have been added to manage views: `addView`, `removeView`, and `getView`. `addView` must be supplied an `HTMLElement` or `string` with the ID of an `HTMLElement` where the new view will be situated. `removeView` takes a `ViewKey` and removes the associated view. `getView` takes a `ViewKey` and returns the `View` it belongs to.

Legacy Viewer

The legacy viewer (the pre-ESM viewer) shares an engine with the ESM viewer and thus the engine is aware of the concept of multi-views even though there should be no actual API changes. Everything that worked before should still work, any behavior that has changed due to multi-canvas is a bug.

## Limitations

- Cutting planes work, but if there are several views, capping will only be drawn in one of them after a cutting plane drag. An update to a view will be drawn with capping intact.
- Some effects such as simple shadow and bloom might behave poorly on certain systems if your canvases are of different sizes.
- Certain selections such as sphere or convex polyhedron selections will operate on the visibility state of the default view.

Conversation saved
HOOPSY BETA

### Hello! I'm HOOPSY

Your Docs generative AI assistant. Ask me anything about HOOPS Visualize Web or choose a sample question below to start a conversation:

What is HOOPS Visualize Web?
What are the latest release notes for HOOPS Visualize Web?
How do I start evaluating HOOPS Visualize Web?
How do I write my first sample application?
How can I get assistance?

HOOPSY may store conversations according to OpenAI's policy. Responses may not always be accurate.

HOOPSY is thinking...