The Voxxlr viewer is embedded as an iframe that exchanges messages with its parent window using the HTML channel messaging API. A message consists of a name and an object containing the required arguments, as well as an optional object containing user-defined data. Voxxlr provides the vx-viewer web component which encapsulates the message exchange into an object with a functional interface as shown in the example below.
Messages should only be sent to the viewer after it has been loaded, which is guaranteed when the viewer.load message handler is invoked. In this example the handler turns on logging, requests the orbital camera controller and listens to error messages. Note how the vx-viewer is initialized in the HTML document using a URL containing a document token. It can also be initialized via the vx-viewer.init function
The table below list the complete interface of the vx-viewer component. It is important to note the iframe mirrors all messages it receives back to the parent window including all parameters and user defined data. This mechanism enables synchronous communication and provides a means for implementing an MVC pattern. The Voxxlr editor extensively relies on message mirroring and provides a reference on how to utilize it.
|post (name,arguments,custom)||posts a single message to the viewer. The function also accepts arrays for each of the arguments in order to pass multiple messages at once.|
|wait (name,arguments,custom)||posts a single message to the viewer and returns a promise which resolves when the mirrored message from the viewer is received. This function has to be called with an await.|
installs an event handler for a message type produced by the viewer. Upon receipt, the vx-viewer will invoke the callback as
callback(arguments, custom, name, owner)
The optional owner argument is only required to identify the callback in the un function documented below. If un is never called the owner parameter is not required.
|un (name,owner)||Uninstalls all message handlers for the given name and owner|
|import(document||token, config, meta)||Loads an additional document into the viewer. Calling this function is equivalent to posting an import.load message with the appropriate arguments. The first parameter to this function can either be a document token or a complete document object retrieved via the /list or /load REST calls to app.voxxlr.com, respectively. The config parameter is a user defined object which may contain a transformation matrix, and the meta parameter is an optional array defining which meta data objects to load with the document.|
|init(token)||Initializes the viewer with a different document. This function is equivalent to changing the source of the iframe. It returns a Promise which resolves when the iframe onload message has been received. This function should be called with an await|
The API explorer below lets you interactively send and receive messages from the viewer embedded on the right hand side. Simply click on a message to inspect the json object that was sent on the bottom left and the response from the viewer on the bottom right. Note that some actions such as creating a measurement requires a sequence of messages to be exchanged. As the state of this interaction changes different message types are enabled and the instructions below the viewer on the right change accordingly. Note that some messages are common to all of the supported data types while others are specific to each type. You can also open the sandbox in a standalone window.
Voxxlr currently supports three different camera controllers, orbiter, flyer and walker as well as a navigation cube and target indicator. The example below shows how to switch between the orbiter and flyer and how to place the target. Note how two messages are sent in a single invocation of viewer.post
A viewpoint stores the entire state of the viewer and currently loaded document, including camera location and mode, hidden measurements and annotations, the visualization mode and so forth. The tabs at the top of the Voxxlr editor are implemented using viewpoints. The example below shows how to record and set a viewpoint as well as taking a screenshot of the viewer
Voxxlr supports three geometric primitives, line, polygon and floodfill. Each produces different measurements depending on the current mode. When the viewer receives a .record message such as line.record, it switches into an input mode, requiring the user to define control points inside the model. After enough control points to complete a primitive have been collected, the viewer mirrors the .record message back to the parent window. Note that the actual primitive is not created until the viewer receives a corresponding .create message.
A geometric primitive can be selected for editing via the .select message, which is usually a response to a .click or .dblclick message triggered by the viewer when the users attempts to select a primitive. Subsequent changes due to the user moving control points in the viewer are communicated back to the editor via the .update message. The Voxxlr editor, for example, saves all measurements as meta data objects to the document using the REST API of doc.voxxlr.com. When a document is loaded, the editor retrieves the meta data and creates the measurements via the .create messages..
|init ()||The init functions is called once when the point primitive is created. In the example below this function loads an image.|
|render2d(ctx, state)||This function is called whenever the viewer has to render the point primitive. ctx is a handle to the current 2d canvas context and state contains viewer specific information about the primitive such as the current scale and timestamp. Note that the render function function must return a boolean to indicate whether the object is fully rendered. To implement an animation, true has to be returned in order to trigger a subsequent repaint.|
|render3d(...) - coming soon||The render3d function will provide an interface to draw the point geometry in the 3D canvas using WebGL.|
|update(scope)||This function is optional and called every time the primitive receives a point.update message. The scope parameter passed to update is part of the message content. This function is generally used to update the scope to which the functions in the code object are bound. In the example below it is used to change the radius of the icon.|
|intersect(ctx, x, y, state)||This function is optional and called to determine if the point primitive intersects the x,y coordinates on the screen. This function is generally called to determine if a mouse click occurred on the primitive. ctx is passed to enable HTML canvas based collision detection mechanism.|
The functions provided to the point primitive determine how it looks and behaves, but it is the parent application that defines what a primitive represents and what occurs when it is selected. The Voxxlr editor, for example, provides three different types of annotations based on the point primitives. The examples below shows how to create an annotation consisting of an SVG icon surrounded by an animated circle. The "Larger" and "Smaller" buttons trigger a point.update message which in turn triggers the update function of the primitive to increase the radius stored in the this scope
Voxxlr provides mechanisms to import other documents on the platform. This general only applies to similar data types such as Point Clouds and 3D Models and the corresponding messages may have no effect for incompatible data types. Importing a document requires either a document token or a complete document object. The vx-viewer provides an import function that accepts either as a parameter. Internally it post import.load message
The vx-viewer as well as other components encapsulating various high level concepts can be found at the app.voxxlr.com domain as well as on github. The example below, for example, uses the hierarchy component to display the structure of the 3D model and the tabs component to manage viewpoints.
Note that the Voxxlr editor itself is an App, and can thus be used as a reference implementation. The complete source code of the editor as well as a number of predefined web components can be found on github. If you have questions or need support in developing Apps please contact firstname.lastname@example.org