My use case was doing a simple interface for an RGB-D visual odometry algorithm. Basically an algorithm that you feed with images and it tries to reconstruct a 3D model and the camera trajectory.
The algorithm is coded in Rust and exposed through a wasm api thanks to wasm-bindgen itself exposed as javascript object thanks to wasm-pack. The three exposed struct are WasmTracker
, PointCloud
and CameraPath
, each with very few public methods.
I have made a simplification hypothesis that all these structs are going to be singletons. This enables me to have only 1 ES6 module (Renderer
) keeping internally “global” variables with all useful state and thus reducing communication with Elm to a minimum. This ES6 module also contains a custom element instantiated by Elm and that enables Elm -> wasm communication through the custom elements attributes.
Concretely I have the following communication through ports:
port loadDataset : Value -> Cmd msg
port datasetLoaded : (Int -> msg) -> Sub msg
port newKeyFrame : (Int -> msg) -> Sub msg
port track : () -> Cmd msg
port exportObj : () -> Cmd msg
As you can see, very minimal types, so no decoder / encoder needed. And the custom element is populated like this:
Html.node "custom-renderer"
[ attribute "width" (String.fromFloat width)
, attribute "height" (String.fromFloat height)
, attribute "canvas-id" "canvas-kf"
, attribute "nb-frames" (String.fromInt nb_frames)
, attribute "current" (String.fromInt s.current)
]
With only the current
value changes (slider) triggering wasm code to be executed through functions in the ES6 module:
attributeChangedCallback(name, oldValue, newValue) {
switch (name) {
case 'current':
if (newValue === oldValue) break; // Do not accidentally trigger.
updateCurrentPointCloud(+newValue);
updateCurrentCameraPoseKf(+newValue);
updateCurrentKfImage(+newValue);
break;
}
}
If you are interested, the demo is available on github with source code. To run it you need a certain kind of dataset. I have one ready here. Beware, it is a 400Mb tar file and once loaded in the app, it will take 900Mb memory (close tab to free memory).