Blog

Multiple WebGL Canvases On a Single Page

2017-04-06

One time, somebody on the forum asked an interesting question about using several Canvas elements on a single page. Back then, I thought “Why would anybody need this?”. But after seeing many well-crafted applications, including ones from the well-known Animagraffs studio, I’m not so sure anymore. If you have doubts, then look into the demo page, for example, at the ISS 3D information graphics.

This intriguing feature provided to us by the Blend4Web developers deserves a close examination.

What’s the Point

If you try to initialize several Canvas elements in your script, you will naturally get an error, as the engine uses lots of its own variables to store operation conditions. This is understandable. So, in such cases, the developers recommend using the “namespace” concept.

Here is the idea of it: user’s web browser, as usual, loads one and only one engine file. However, you also set specific identifiers (namespaces) in your scripts, and these identifiers allow the engine to process your scripts as if they were separate units that work independently from each other.

A Bit of Practice

First, we will have to prepare a place for several Canvases in the HTML body. I will use a standard template that Project Manager generates when we create a new project.

So, here is the task: we need to place two independent Canvas elements on the page. Accordingly, let’s define DIV containers in the HTML file:

<body>
    <div id="canvas_container1"></div>
    <div id="canvas_container2"></div>
</body>

Let’s say that implemented code for different containers should be stored in different JavaScript files. Add the lines we need to the HTML:

<script type="text/javascript" src="canvas1.js"></script>
<script type="text/javascript" src="canvas2.js"></script>	

We also need to define location, size and other parameters in the CSS file:

#canvas_container1 {
  position: absolute;
  left: 0px;
  top: 0px;
  width: 640px;
  height: 480px;
}

#canvas_container2 {
  position: absolute;
  left: 0px;
  top: 500px;
  width: 640px;
  height: 480px;
}

And now comes the most interesting part. We only have to set the identifier while initializing the module in the b4w.require function so the engine would know to which namespace the script belongs. However, internal require function calls should not use any identifiers.

In the end, standard code generated by the Project Manager should look like this:

// register the application module
b4w.register("canvas1", function(exports, require) {

// import modules used by the app
var m_app       = require("app");
var m_cfg       = require("config");
...
b4w.require("canvas1","canvas1").init();

And the code for the second canvas should look like:

// register the application module
b4w.register("canvas2", function(exports, require) {

// import modules used by the app
var m_app       = require("app");
var m_cfg       = require("config");
...
b4w.require("canvas2","canvas2").init();

Interaction Between Two Canvases

Let’s take a look at a more complex example, where codes for different Canvas elements can interact with each other. Let’s try to start an animation on the first Canvas with a mouse click in the second Canvas window.

Define the external function “ext_method” for starting animation in the first Canvas code:

...
exports.ext_method = function() {
    var o = m_scs.get_object_by_name("cube");
    m_anim.apply_def(o);
    m_anim.play(o);
}
...

In the second Canvas code, define the animation function using require and set the identifier of the Canvas you need as a parameter. Note that in this case the require method is called from the global object b4w:

...
var m_ext_canv  = b4w.require("canvas1", "canvas1");
...
Add the standard code for processing “click” event:
...
function init_cb(canvas_elem, success) {

    if (!success) {
        console.log("b4w init failure");
        return;
    }
...
    canvas_elem.addEventListener("mousedown", main_canvas_click, false);
    canvas_elem.addEventListener("touchstart", main_canvas_click, false);
}

...
function main_canvas_click() {
    m_ext_canv.ext_method();
}

As you can see, there is nothing difficult in working with multiple Canvases, and still it opens the door to amazing opportunities!

Example source files.

Comments
09 may. 2023 07:44
Reply to post of user medikid
hi,
could you please fix example source files??!! all those scripts are nowhere to be found
(../../src/ext/**.js etc., leading nowhere… )
thank you!
mgk
hello
18 may. 2023 11:41
good
27 may. 2023 11:13
I clicked on it and it took me to the new version then when reloaded it went back to old. If you still got trains to come home when the new one starts do they get suspended till the features come back?
06 sep. 2023 17:57
ddd
19 oct. 2023 01:26
I also facing this sort of issue with my website page name order taking call center can anyone help so i can share the details in separate thread, Thanks
10 dec. 2023 16:41
wadawdwadwadwadwad
Please register or log in to leave a reply.