4 changed files with 170 additions and 142 deletions
@ -1,10 +1,12 @@ |
|||
import 'package:get/get.dart'; |
|||
import '../controllers/meeting_details_controller.dart'; |
|||
import '../controllers/mind_map_controller.dart'; |
|||
|
|||
class MeetingDetailsBinding extends Bindings { |
|||
@override |
|||
void dependencies() { |
|||
// 注册控制器 |
|||
Get.lazyPut<MeetingDetailsController>(() => MeetingDetailsController()); |
|||
Get.lazyPut<MindMapController>(() => MindMapController()); |
|||
} |
|||
} |
|||
|
|||
@ -0,0 +1,155 @@ |
|||
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>(); |
|||
|
|||
@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 src="https://cdn.jsdelivr.net/npm/markmap-lib"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/markmap-view"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/markmap-toolbar"></script> |
|||
<script src="https://cdn.jsdelivr.net/npm/save-svg-as-png@1.4.17/lib/saveSvgAsPng.min.js"></script> |
|||
<style> |
|||
html, |
|||
body { |
|||
width: 100%; |
|||
height: 100%; |
|||
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: 20px; |
|||
right: 20px; |
|||
} |
|||
|
|||
.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); |
|||
|
|||
async function captureImage() { |
|||
const markmapElement = document.getElementById('markmap'); |
|||
markmapElement.style.height = `${1.sw}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) |
|||
..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('分享完成!'); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue