|
@@ -1,16 +1,175 @@
|
|
|
-# webview_demo
|
|
|
+## WebViewX Demo
|
|
|
+[adrianflutur/webviewx (github.com)](https://github.com/adrianflutur/webviewx)
|
|
|
|
|
|
-A new Flutter project.
|
|
|
+先启动 example 尝试一下加载一个外部带 threejs 示例的网站
|
|
|
|
|
|
-## Getting Started
|
|
|
+基本没有问题,交互也很流畅
|
|
|
+唯一要注意的一点就是,在webview上面不能覆盖flutter组件,会导致无法点击
|
|
|
|
|
|
-This project is a starting point for a Flutter application.
|
|
|
+### 载入 Flutter 内 assets 下的 html 文件
|
|
|
+首先将 html 文件放入 assets 文件夹下,然后调用 `loadContent` 方法就可以载入了,但是有个限制就是 html 文件内的 `<script>` 标签不能获取到本地的 `js` 文件
|
|
|
+```dart
|
|
|
+webviewController.loadContent(
|
|
|
+ 'threejsview/MainPage.html',
|
|
|
+ SourceType.html,
|
|
|
+ fromAssets: true,
|
|
|
+);
|
|
|
+```
|
|
|
+想要加载自己的 `js` 文件,还需要手动传入
|
|
|
+```dart
|
|
|
+/// A set of [EmbeddedJsContent].
|
|
|
+///
|
|
|
+/// You can define JS functions, which will be embedded into
|
|
|
+/// the HTML source (won't do anything on URL) and you can later call them
|
|
|
+/// using the controller.
|
|
|
+///
|
|
|
+/// For more info, see [EmbeddedJsContent].
|
|
|
+@override
|
|
|
+final Set<EmbeddedJsContent> jsContent; // 此变量接受一串 js 文本集合
|
|
|
+```
|
|
|
|
|
|
-A few resources to get you started if this is your first Flutter project:
|
|
|
+一般可以这样将 `js` 传入 🚧【但是此方式存在问题,`initState` 中的异步操作不会执行】
|
|
|
+```dart
|
|
|
+/// 错误示例 🚧
|
|
|
+final javaScriptsFromAssets = [];
|
|
|
|
|
|
-- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
|
|
|
-- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
|
|
|
+void initState() {
|
|
|
+ ///...
|
|
|
+ final ScriptsList = [
|
|
|
+ "threejsview/js/build/three.js",
|
|
|
+ "...",
|
|
|
+ ];
|
|
|
+ for (String path in ScriptsList) {
|
|
|
+ _loadJSFromAssets(path).then((value) {
|
|
|
+ javaScriptsFromAssets.add(value);
|
|
|
+ });
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
-For help getting started with Flutter, view our
|
|
|
-[online documentation](https://flutter.dev/docs), which offers tutorials,
|
|
|
-samples, guidance on mobile development, and a full API reference.
|
|
|
+///buildWebViewX 时候这样传入
|
|
|
+Widget _buildWebViewX() {
|
|
|
+ return WebViewX(
|
|
|
+ //...
|
|
|
+ jsContent: javaScriptsFromAssets.map((e) => EmbeddedJsContent(js: e)).toSet(),
|
|
|
+ );
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+需要改用 `FutureBuilder`
|
|
|
+```dart
|
|
|
+Future<String> _preloadJS() async {
|
|
|
+ final scriptsList = [
|
|
|
+ "threejsview/js/build/three.js",
|
|
|
+ ///...
|
|
|
+ ];
|
|
|
+ for (String path in scriptsList) {
|
|
|
+ var value = await _loadJSFromAssets(path);
|
|
|
+ javaScriptsFromAssets.add(value);
|
|
|
+ }
|
|
|
+ return Future.value("");
|
|
|
+ }
|
|
|
+
|
|
|
+Widget _buildWebViewX() {
|
|
|
+return FutureBuilder<String>(
|
|
|
+ future: _preloadJS(),
|
|
|
+ builder: (context, AsyncSnapshot<String> snapshot) {
|
|
|
+ if (snapshot.hasData) {
|
|
|
+ return WebViewX(
|
|
|
+ ///...
|
|
|
+ jsContent: javaScriptsFromAssets
|
|
|
+ .map((e) => EmbeddedJsContent(js: e))
|
|
|
+ .toSet(),
|
|
|
+ ///...
|
|
|
+ );
|
|
|
+ } else {
|
|
|
+ return const CircularProgressIndicator();
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+```
|
|
|
+这里有两种类型的 JS 传入,`js` 是一种 `webJs` 和 `mobileJs` 是另一种
|
|
|
+- `js` 是注入与平台无关的代码
|
|
|
+- `webJs` 和 `mobileJs` 是根据平台注入对应的代码
|
|
|
+
|
|
|
+
|
|
|
+### 关于 Assets 内资源文件打包的说明
|
|
|
+需要在 Dart 代码下获取的文件需要写入 `pubspec.yaml` 来进行打包
|
|
|
+```yaml
|
|
|
+flutter:
|
|
|
+ uses-material-design: true
|
|
|
+ assets:
|
|
|
+ - threejsview/
|
|
|
+ - threejsview/js/gui/
|
|
|
+ - threejsview/js/customScript/
|
|
|
+ - threejsview/js/customScript/utility/
|
|
|
+ - threejsview/js/customScript/manager/
|
|
|
+ - threejsview/js/customScript/clipWorkflow/
|
|
|
+ - threejsview/js/controls/
|
|
|
+ - threejsview/js/build/
|
|
|
+```
|
|
|
+
|
|
|
+但是在 JS 代码下获取的文件,不需要写入配置,只要将文件放入项目根目录下的 `web` 文件夹即可,因为 JS 执行的资源文件获取是从 build 文件夹根目录获取的,而 Dart 打包的资源文件会自动放入 assets 文件夹下,在 Dart 获取 assets 内的文件时,路径头 `assets/` 是缺省值
|
|
|
+
|
|
|
+### Flutter 内的 Dart 触发 Webview 内部 JS 方法
|
|
|
+在 webviewX 插件下,外部调用内部方法只需要这样写
|
|
|
+```dart
|
|
|
+webviewController.callJsMethod("method_name",["paramA","paramsB"])
|
|
|
+```
|
|
|
+
|
|
|
+也可以用一个变量来接受 js 函数的返回值
|
|
|
+```dart
|
|
|
+var resultFromJs = await webviewController.callJsMethod("method_name",["paramA","paramsB"])
|
|
|
+print(resultFromJs);
|
|
|
+```
|
|
|
+
|
|
|
+### Webview 内的 JS 触发 Flutter 内部 Dart 方法
|
|
|
+首先在 `_buildWebViewX` 时需要定义好 `DartCallback`
|
|
|
+```dart
|
|
|
+dartCallBacks: {
|
|
|
+ DartCallback(
|
|
|
+ name: 'TestDartCallback',
|
|
|
+ callBack: (msg) => showSnackBar(msg.toString(), context),
|
|
|
+ ),
|
|
|
+ DartCallback(
|
|
|
+ name: 'Dart_GetClipPlaneData',
|
|
|
+ callBack: (msg) {
|
|
|
+ print("WebView 触发 Dart_GetClipPlaneData ${msg.toString()}");
|
|
|
+ final result = {'ErrorCode': "1001"};
|
|
|
+ return jsonEncode(result);
|
|
|
+ },
|
|
|
+ )
|
|
|
+ },
|
|
|
+```
|
|
|
+
|
|
|
+参数的传递可用利用 JSON 序列化 Dart Object 或者 JS Object
|
|
|
+webview 下直接通过定义好的函数名就可以触发
|
|
|
+```js
|
|
|
+let inputData = {
|
|
|
+ PointsList: mappingPoints,
|
|
|
+ ClipImageName: imageName
|
|
|
+};
|
|
|
+let json = Dart_GetClipPlaneData(JSON.stringify(inputData));
|
|
|
+return JSON.parse(json);
|
|
|
+```
|
|
|
+
|
|
|
+可以通过参数传入 Base64 编码的图像,在 threejs 中作为纹理贴图
|
|
|
+```dart
|
|
|
+final faceImages = [
|
|
|
+ _loadRandomImage(500, 500),
|
|
|
+ _loadRandomImage(500, 500),
|
|
|
+ _loadRandomImage(500, 500),
|
|
|
+ _loadRandomImage(500, 500),
|
|
|
+ _loadRandomImage(500, 500),
|
|
|
+ _loadRandomImage(500, 500),
|
|
|
+];
|
|
|
+// print([759, 596, 397, ...faceImages]);
|
|
|
+try {
|
|
|
+ await webviewController
|
|
|
+ .callJsMethod('changeSurface', [759, 596, 397, ...faceImages]);
|
|
|
+} catch (e) {
|
|
|
+ showAlertDialog(
|
|
|
+ executeJsErrorMessage,
|
|
|
+ context,
|
|
|
+ );
|
|
|
+}
|
|
|
+```
|