In this Article

In this two parts article, I will demonstrate how easy it can be to integrate a 3D engine like BabylonJS into a business application built with a SPA framework like Angular. You will see how those two frameworks can interact with each other and where possible performance pitfalls may occur.

Article Series

  1. Integration Basics: Integrating BabylonJS 3D Engine Into an Angular Business Application - Part 1 ⬅
  2. Performance optimization: Integrating BabylonJS 3D engine into an Angular business application - Part 2
  3. 🇩🇪Architekturlösung für die Integration von Angular und BayblonJS - Demo und Integrationsbeispiele

What to expect in part 1

This part is about the integration basics of BabylonJS and Angular. I will show you how you can use your existing knowledge of Angular and combine it with a graphics engine to create a compelling and modern user experience. You can find the performance-related aspects in part 2.

Integration Demo, BabylonJS and Angular working together

Take a look at the demo below, this is what we will discuss here. More specific, I will demonstrate how to implement the first tab (unoptimized), the other versions are discussed in part 2.

Demo Prefview

A Primer on BabylonJS

BabylonJS is a 2D/3D engine for the web and is based on the WebGL standard. It is possible to create complex visualizations, configurator tools, or games that run blazingly fast and are easy to use.

In contrast to other engines like Unity or Unreal, content created with BabylonJS is written in JavaScript or TypeScript. This means that it runs natively in the browser and therefore we can enter, manipulate, and extend the graphic content generation at any time. This is key for an easy integration between any graphics engine and SPA frameworks.

Where to start

Angular is a well-known application framework and you surely know how to use it. However, you might not yet know the intrinsics and basics of BabylonJS. BabylonJS provides us with a number of concepts and API interfaces that we need to integrate with our Angular code. The most important objects in the API are Engine and Scene. A closer look will show that they are similar to Angular services and components, concept-wise.

Before we start, we have to make a few assumptions:

  1. The Engine resembles an Angular service
  2. The Engine renders a Scene
  3. A Scene corresponds to an Angular component
  4. A Scene holds information about its state

An engine works by rapidly rendering the scene image by image, this is called the renderLoop.

In the next paragraphs, I will demonstrate you my approach to integrate Angular and BabylonJS.

Providing the Engine as an Angular Service

As mentioned, the Engine can be compared to a service. What we have to do is to manage the state and provide it to the engine.

We embed the Engine by using an Angular service as our singleton and proxy to the Engine.

// store the Engine
engine: Engine;


// the Engine will render into the Canvas element
start(canvas: ElementRef<HTMLCanvasElement>, scene: Scene) {
  this.engine = new Engine(this.canvas, true);

  // ... you can add content to the Scene

  // ignore the change events from the Engine in the Angular ngZone
  this.ngZone.runOutsideAngular( () => {
    // start the render loop and therefore start the Engine
    this.engine.runRenderLoop(() => scene.render())
  });
}

Create the "engine" with some content and start the render loop.

The service holds the Engine state, but we also need a way to manipulate the Scene. Each Scene could correspond to an Angular component.

The Scene Component

Using an Angular component, we integrate the Scene perfectly in our existing architecture.

The component template must contain a Canvas and a reference where the graphics will be rendered:

<div class="wrapper">
    <canvas #rCanvas id="rCanvas"></canvas>
</div>

That reference will be selected by our component and is provided to the service.

// ...
@ViewChild('rCanvas', {static: true})
canvasRef: ElementRef<HTMLCanvasElement>;

private scene: Scene;

constructor(private readonly engineService: EngineService) {}

// ...
ngOnInit(): void {
  // .. manipulate the scene
}

ngAfterViewInit(): void {
    // start the Engine
    // be aware that we have to setup the Scene before
    this.engineService.start();
}

The scene component calling the created Angular EngineService to start the graphics engine

Notice: To be sure that the Canvas element is available in the DOM, the Engine service is started after the view has been initialized.

But even if we are now able to display things, there are no interactions possible, yet. How can these two separate systems interact?

Interaction between Angular and BabylonJS

Now that everything is set up, we can begin to implement interactions between our graphics framework and the business application framework.

As discussed, the Engine renders the Scene in a loop, and therefore, we can change the Scene, and the Engine will update the rendered image accordingly.

Creating interaction with the scene is as easy as subscribing to any event in Angular, in our case listening to changes of our configuration object. The renderLoop will do the rest by updating the rendered scene on the next iteration.

this.preferences.config.subscribe(config => {
    // update config
    this.someConfig = config;
    // change / update asteroids
    this.updateElements();
});

The scene component, listening to configuration changes

The other way round from BabylonJS to Angular is also straightforward: We add an event listener to e.g. the Scene we want to interact with and do something with the event we receive.

const jupyter = this.engineService.createObject('jupyter');
jupyter.actionManager = new ActionManager(this.engineService.scene);
jupyter.actionManager.registerAction(new ExecuteCodeAction(ActionManager.OnPickUpTrigger,
      () => this.onJupyterClick.next());

Creating a Scene object and adding an action to it

The ActionManager, ExecuteCodeAction, and OnPickUpTrigger objects are BabylonJS's way to register an onClicked listener that executes a function. In this case, we will pass on the request and increase a click counter.

As you can see, integrating BabylonJS into Angular is straightforward, interaction is as easy as calling a function.

Conclusion

At this point, we have integrated Angular and BabylonJS. However it is not performant yet. Take a look at the Stackblitz demo and select unoptimized to see the effect of our doing so far.

Wrap Up

That's it! We successfully integrated the 2D/3D graphics engine BabylonJS in our business application written with Angular and Typescript.

In part 2, you will see where performance pitfalls are, how to find and avoid them. Subscribe to our monthly newsletter to not miss the next article.

Do you need support integrating 3D in your Business Application?

You're at a critical stage in an important project? You have critical architectural questions or want external validation of your concepts and ideas? If you give us your contact information, we'll contact you to discuss options with you.

Sending ...
Thank you! Your contact request has been received and one of our colleagues will respond within the current or next business day.
Oops! Something went wrong while submitting the form.
Please enter a valid email address, name and message.

Related Articles

babylonjs
Architekturlösung für die Integration von Angular und BayblonJS - Demo und Integrationsbeispiele
In diesem Artikel werde ich zeigen wie Angular und BabylonJS erfolgreich und zukunftssicher integriert werden. Beide Frameworks – Angular als Business-Application-Framework und BabylonJS als Graphics-Engine – sind auf dem jeweiligen Gebiet gestandene Beispiele und damit perfekt…
Max Schulte
babylonjs
Performance optimization: Integrating BabylonJS 3D engine into an Angular business application - Part 2
Welcome to the second part of this blog post series. If you want to learn how to basically integrate BabylonJS into Angular (or vice versa) please take a look at part 1. In this post, our goal is to make your application and the interactions fast! Article Series Integration…
Max Schulte
web components
The Flaws of Web Components (and possible solutions): Perks & Flaws Series - Part 3
The first article of this series introduced into the motivation for using Web Components. After looking at the perks in the second part, we are going to learn about the flaws of Web Components in this article. Please note that with the on-going development of the standards, some…
Manuel Rauber
angular
Creating Expressive Toast Components with Angular Animations
In some of my recent projects, I have experienced the need and requirements for better user experience by incorporating animations into Angular-based user interfaces. In this article, I am showing you how you can create an expressive toast component with Angular animations…
Konstantin Denerz