Jimmy a591021a6a some test | 2 years ago | |
---|---|---|
.vscode | 2 years ago | |
android | 2 years ago | |
ios | 2 years ago | |
lib | 2 years ago | |
test | 2 years ago | |
threejsview | 2 years ago | |
web | 2 years ago | |
windows | 2 years ago | |
.gitignore | 2 years ago | |
.metadata | 2 years ago | |
README.md | 2 years ago | |
analysis_options.yaml | 2 years ago | |
pubspec.lock | 2 years ago | |
pubspec.yaml | 2 years ago |
adrianflutur/webviewx (github.com)
先启动 example 尝试一下加载一个外部带 threejs 示例的网站
基本没有问题,交互也很流畅 唯一要注意的一点就是,在webview上面不能覆盖flutter组件,会导致无法点击
首先将 html 文件放入 assets 文件夹下,然后调用 loadContent
方法就可以载入了,但是有个限制就是 html 文件内的 <script>
标签不能获取到本地的 js
文件
webviewController.loadContent(
'threejsview/MainPage.html',
SourceType.html,
fromAssets: true,
);
想要加载自己的 js
文件,还需要手动传入
/// 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
中的异步操作不会执行】
/// 错误示例 🚧
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
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
是根据平台注入对应的代码需要在 Dart 代码下获取的文件需要写入 pubspec.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/
是缺省值
在 webviewX 插件下,外部调用内部方法只需要这样写
webviewController.callJsMethod("method_name",["paramA","paramsB"])
也可以用一个变量来接受 js 函数的返回值
var resultFromJs = await webviewController.callJsMethod("method_name",["paramA","paramsB"])
print(resultFromJs);
首先在 _buildWebViewX
时需要定义好 DartCallback
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 下直接通过定义好的函数名就可以触发
let inputData = {
PointsList: mappingPoints,
ClipImageName: imageName
};
let json = Dart_GetClipPlaneData(JSON.stringify(inputData));
return JSON.parse(json);
可以通过参数传入 Base64 编码的图像,在 threejs 中作为纹理贴图
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,
);
}