Syncing Multiple Viewers
In this chapter, we will create a viewer helper class to keep our viewer states synchronized.
- Managing Multiple Viewers
- Traversing the Model Tree
There are a few ways you could approach synchronizing both viewers, like passing in the second viewer to the operator and making the same calls again on that viewer, but that would create high coupling between separate WebViewer objects. Therefore, you can abstract that same concept into an external helper class that manages any viewers in the application. While we will only have two viewers in this application, the helper class can be extended to an arbitrary number of viewers.
In this section, we will be building the SyncHelper class located in the file src/js/SyncHelper.js. The purpose of this class is to query the model state in the main viewer (the source of truth), and then update all other viewers attached. The constructor will take in an array of WebViewer objects and assign the first element as the mainViewer. All subsequent viewers are "attached viewers" that are updated to reflect the main viewer's state.
We need a function that executes when a node transformation occurs in the mainViewer. The function will gather all the transforms for the node IDs provided, and make sure the attachedViewers set their model's respective nodes to the same values.
We will use a Map to store the nodeId and its transformation matrix as a key-value pair. Then we use that Map to set the node matrices for the attached viewers.
Add syncNodeTransforms() as a member function of SyncHelper:
In the event nodeIds is empty, we should gather all the nodes of the mainViewer starting at the root node. First, we will add a helper function to recursively gather all nodeIds of the mainViewer.
Now we can prepend syncNodeTransforms() with the following:
Last, let's write some accessor member functions for later use.
With this in place, let's go back and instantiate this SyncHelper class in our main application. In our main constructor, we will instantiate a SyncHelper object after we have created both WebViewer objects. Add this._viewSync = new SyncHelper(this._viewerList); to the constructor in app.js:
Recall the handleEvent callback function in app.js from the previous section. This callback will be a great place to add our new syncNodeTransforms() function. Update the handleEvent callback with the following:
You should now be able to select a part in the Main View, add handles with the "Show Handles" button, and watch the respective part in the "Overhead View" move.