You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
4.5 KiB

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'meeting_details_controller.dart';
class MindMapController extends GetxController {
late final WebViewController webViewController;
final _meetingDetailsController = Get.find<MeetingDetailsController>();
final double _width = 1.sw - 25.w;
bool isWebViewReady = false;
@override
void onInit() {
super.onInit();
String html = '''
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MindMap</title>
<script>${_meetingDetailsController.markmapLibJs}</script>
<script>${_meetingDetailsController.d3Js}</script>
<script>${_meetingDetailsController.markmapViewJs}</script>
<script>${_meetingDetailsController.markmapToolbarJs}</script>
<script>${_meetingDetailsController.saveSvgAsPngJs}</script>
<style>
html,
body {
width: 100%;
height: 100%;
min-width: ${_width}px;
min-height: ${_width}px;
margin: 0;
padding: 0;
overflow: hidden;
}
.mind-map {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.mind-map #markmap {
width: 100%;
height: 100%;
}
.mind-map .mm-toolbar {
height: 30px;
background: #fff;
border: 1px solid #d0d5dd;
border-radius: 8px;
display: flex;
justify-content: space-around;
align-items: center;
position: absolute;
top: 10px;
right: 2px;
}
.mind-map .mm-toolbar-item {
width: 24px;
height: 24px;
border-radius: 6px;
cursor: pointer;
color: #101828;
display: flex;
justify-content: center;
align-items: center;
}
.mind-map .mm-toolbar-item.active {
background-color: #d4d4d8;
}
</style>
</head>
<body>
<div class="mind-map">
<svg id="markmap"></svg>
<div id="toolbar"></div>
</div>
<script>
const { Transformer, Markmap, Toolbar } = window.markmap;
const transformer = new Transformer();
const { root } = transformer.transform(`${_meetingDetailsController.meetingDetails.value.summary}`);
let mm = Markmap.create('#markmap', {
maxWidth: 300,
initialExpandLevel: 3,
}, root);
const toolbar = Toolbar.create(mm);
toolbar.showBrand = false
toolbar.render();
const el = toolbar.el;
const toolbarElement = document.getElementById('toolbar');
toolbarElement.append(el);
window.captureImage = async function() {
const markmapElement = document.getElementById('markmap');
markmapElement.style.height = `${_width}px`;
await mm.fit();
const options = {
scale: 2,
backgroundColor: '#FFFFFF',
encoderOptions: 1,
};
const uri = await svgAsPngUri(markmapElement, options);
markmapElement.style.height = '100%';
mm.fit();
if (window.ImageChannel) {
window.ImageChannel.postMessage(uri);
}
}
</script>
</body>
</html>
''';
webViewController = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted)
..setNavigationDelegate(
NavigationDelegate(
onPageFinished: (String url) {
isWebViewReady = true;
},
),
)
..addJavaScriptChannel(
'ImageChannel',
onMessageReceived: _messageReceived,
)
..setBackgroundColor(Colors.transparent)
..loadHtmlString(html);
}
void _messageReceived(message) async {
final String dataUrl = message.message;
final String base64Str = dataUrl.split(',').last;
final Uint8List bytes = base64.decode(base64Str);
final String fileName =
'${_meetingDetailsController.meetingData.value.title} mindmap.png';
final tempDir = await getTemporaryDirectory();
final File file = File('${tempDir.path}/$fileName');
await file.writeAsBytes(bytes);
final result = await SharePlus.instance.share(ShareParams(
text: '分享思维导图',
files: [XFile(file.path)],
));
if (result.status == ShareResultStatus.success) {
EasyLoading.showToast('分享完成!');
}
}
}