Using EvaluateJavascript to interact with BabylonJS models through Flutter Webview

Hi!
I am new to babylonjs and I intend to use it within a Flutter application through a webview plugin. It is not the tidiest implementation, but there are no 3D libraries for Flutter yet so this will have to do for now. I am trying to manipulate a sphere’s position from the flutter application using a slider. I just don’t understand how I can get a handle on an object in babylonjs. I’ve seen an example for this kind of interaction using three.js, with the following evaluateJavascript that gives a rendered cube by the name “cube” a random colour:
controller.data.evaluateJavascript(“cube.material.color.setHex(‘0x’ + Math.floor(Math.random() * 16777215).toString(16));”);

retrieved from this article

I understand this is a very niche question, but does anyone know how I can accomplish this using babylonjs? I am not very familiar with JS overall, so I do not know what are the possibilities when using an evaluateJavascript method. Maybe someone can enlighten me.

Thank you,
Christian

It is not a niche question! It is a fantastic opportunity for all of us to learn how to integrate Babylon.js and 3D rendering in Flutter

Luckily a friend of mine works on Flutter :wink: I pinged him on Twitter to see if someone from Flutter team can chime in (https://twitter.com/deltakosh/status/1224382922926329856?s=20)

That being said, on the JS side, you have to make sure that your cube variable is defined on the global scope. Something like window.cube = ...

2 Likes

Hey Christian,

You’ll need to expose JS APIs that you can invoke from compiled Dart code.

The easiest way to do that is with package:js – see js | Dart Package

You create a stub or facade for the target JS code in Dart and then invoke it directly from your Dart code.

For an of examples of how this works, see GitHub - google/chartjs.dart: Dart API for Chart.js

It’d be a LOT of work to expose all of this API to Dart (although it’d be cool to see!). You’ll likely just want to expose the APIs you need.

Start with something super small and build up from there!

2 Likes

Also take a look at GitHub - FirebaseExtended/firebase-dart: Dart wrapper for Firebase

2 Likes

Hi, thank you for the assistance. I managed to manipulate the cube using “window.cube” and declaring the cube outside of the createScene method in my html file. At first it did not work, because I had not set up the WebViewController correctly. I used this flutter_webview example as a reference: plugins/main.dart at master · flutter/plugins · GitHub

Also thank you kevmoo for the suggestion, it is good to know a different approach for this. This works for me now so I will go with it for now:)

Here is my code for anyone else having trouble with this. By pressing a button, the sphere moves upwards, one step at a time.

import ‘dart:async’;
import ‘package:flutter/material.dart’;
import ‘package:webview_flutter/webview_flutter.dart’;

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State {
final Completer _controller =
Completer();

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text(‘Flutter WebView example’),
),
body: Builder(builder: (BuildContext context) {
return WebView(
initialUrl: ‘file:///android_asset/flutter_assets/assets/bjs.html’,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
);
}),
floatingActionButton: someButton(),
);
}

Widget someButton() {
return FutureBuilder(
future: _controller.future,
builder: (BuildContext context,
AsyncSnapshot controller) {
if (controller.hasData) {
return FloatingActionButton(
onPressed: () async {
_onChangePosition(controller.data, context);
},
child: const Icon(Icons.arrow_upward),
);
}
return Container();
});
}

void _onChangePosition(
WebViewController controller, BuildContext context) async {
final String cookies =
await controller.evaluateJavascript(‘window.sphere.position.y += 1;’);
print(cookies);
}
}

Sorry for the poor formatting, I couldn’t figure out how to keep the indents.

This may help Hello, I am a little confused about a lot of things

1 Like