## WebViewX Demo
[adrianflutur/webviewx (github.com)](https://github.com/adrianflutur/webviewx)

先启动 example 尝试一下加载一个外部带 threejs 示例的网站

基本没有问题，交互也很流畅
唯一要注意的一点就是，在webview上面不能覆盖flutter组件，会导致无法点击

### 载入 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 文本集合
```

一般可以这样将 `js` 传入 🚧【但是此方式存在问题，`initState` 中的异步操作不会执行】
```dart
/// 错误示例 🚧
final javaScriptsFromAssets = [];

void initState() {
    ///...
	final ScriptsList = [
	      "threejsview/js/build/three.js",
	      "...",
	    ];
	for (String path in ScriptsList) {
	  _loadJSFromAssets(path).then((value) {
		javaScriptsFromAssets.add(value);
	  });
	}
}

///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,
  );
}
```
