123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- import 'package:flutter/material.dart';
- import 'dart:ui' as ui;
- import '../../../common/models/index.dart';
- import '../../../common/utils/index.dart';
-
- class SelectNode {
- final NodePaintElement node;
- final RRectPaintElement selectRect;
- SelectNode(this.node, this.selectRect);
- }
- ///
- /// 网络图片异步加载
- ///
- typedef RefreshImage = Function(String, String);
- class MindMapPainter extends CustomPainter {
- final LinePaintElement? linePaintElement;
- final NodePaintElement root ;
- final RRectPaintElement? selectRect;
- final Map<String, ui.Image> mindMapImages;
- final Map<int, ui.Image> priorityImages;
- final Map<int, ui.Image> progressImages;
- final ui.Image? linkIconImage;
- ui.Paint myPaint = ui.Paint();
- MindMapPainter({
- required this.root,
- required this.linePaintElement,
- required this.selectRect,
- required this.priorityImages,
- required this.progressImages,
- required this.linkIconImage,
- required this.mindMapImages
- });
- @override
- void paint(Canvas canvas, Size size) {
- paintNodeInner(canvas, root);
- paintLines(canvas);
- if (selectRect != null) {
- myPaint.style = selectRect!.style.style;
- myPaint.color = selectRect!.style.color;
- myPaint.strokeWidth = selectRect!.style.strokeWidth;
- canvas.drawRRect(selectRect!.rrect, myPaint);
- }
-
- }
- ///
- /// 画节点内部元素
- ///
- void paintNodeInner(Canvas canvas, NodePaintElement node) {
- final elements = node.paintElements;
- // 背景
- if(elements.containsKey(NodeElement.background)) {
- RRectPaintElement? back = elements[NodeElement.background] as RRectPaintElement?;
- if (back != null) {
- myPaint.style = back.style.style;
- myPaint.color = back.style.color;
- canvas.drawRRect(back.rrect, myPaint);
- }
- }
- if(elements.containsKey(NodeElement.border)) {
- RRectPaintElement? border = elements[NodeElement.border] as RRectPaintElement?;
- if (border != null) {
- myPaint.style = border.style.style;
- myPaint.color = border.style.color;
- myPaint.strokeWidth = border.style.strokeWidth;
- canvas.drawRRect(border.rrect, myPaint);
- }
- }
- // 画图片
- if(elements.containsKey(NodeElement.image)) {
- ImagePaintElement? imagePaint = elements[NodeElement.image] as ImagePaintElement?;
- if (imagePaint != null) {
- var url = node.data.image;
- if (node.data.imageId != null && node.data.imageId != 'null' && node.data.imageId?.isNotEmpty == true) {
- url = O2ApiManager.instance.getFileURL(node.data.imageId!);
- }
- if(url != null && url.isNotEmpty && mindMapImages.containsKey(url)) {
- final image = mindMapImages[url];
- myPaint.style = imagePaint .style.style;
- myPaint.color = imagePaint.style.color;
- // print('paint image ,url:$url');
- canvas.drawImageRect(
- image!,
- Rect.fromLTWH(0.0, 0.0, image.width.toDouble(), image.height.toDouble()),
- imagePaint.rect,
- myPaint);
- }
- }
-
- }
- // 优先级
- if(elements.containsKey(NodeElement.priority)) {
- ImagePaintElement? image = elements[NodeElement.priority] as ImagePaintElement?;
- if (image != null) {
- myPaint.style = image.style.style;
- myPaint.color = image.style.color;
- var iconImage = priorityImages[node.data.priority];
- canvas.drawImageRect(
- iconImage!,
- Rect.fromLTWH(0.0, 0.0, iconImage.width.toDouble(), iconImage.height.toDouble()),
- image.rect,
- myPaint);
- }
-
- }
- // 进度
- if(elements.containsKey(NodeElement.progress)) {
- ImagePaintElement? image = elements[NodeElement.progress] as ImagePaintElement?;
- if (image != null) {
- myPaint.style = image.style.style;
- myPaint.color = image.style.color;
- var iconImage = progressImages[node.data.progress];
- canvas.drawImageRect(
- iconImage!,
- Rect.fromLTWH(0.0, 0.0, iconImage.width.toDouble(), iconImage.height.toDouble()),
- image.rect,
- myPaint);
- }
-
- }
- // 文字
- TextPaintElement? text = elements[NodeElement.text] as TextPaintElement?;
- if (text != null) {
- text.painter.paint(canvas, text.offset!);
- }
-
- // 超链接
- if(elements.containsKey(NodeElement.hyperlink)) {
- ImagePaintElement? image = elements[NodeElement.hyperlink] as ImagePaintElement?;
- if (image != null && linkIconImage != null) {
- myPaint.style = image.style.style;
- myPaint.color = image.style.color;
- canvas.drawImageRect(
- linkIconImage!,
- Rect.fromLTWH(0.0, 0.0, linkIconImage!.width.toDouble(), linkIconImage!.height.toDouble()),
- image.rect,
- myPaint);
- }
-
- }
- if(node.children!=null && node.children?.isNotEmpty == true) {
- for(var i=0;i<node.children!.length;i++) {
- paintNodeInner(canvas, node.children![i]);
- }
- }
- }
- ///
- /// 画连接线
- ///
- void paintLines(Canvas canvas) {
- final lines = linePaintElement?.lines;
- if(lines !=null && lines.isNotEmpty) {
- myPaint.style = linePaintElement!.style.style;
- myPaint.strokeWidth = linePaintElement!.style.strokeWidth;
- myPaint.color = linePaintElement!.style.color;
- for (var line in lines) {
- // final bezierControlX = line.start.dx < line.end.dx ? line.start.dx + (line.end.dx - line.start.dx) / 3: line.start.dx - (line.start.dx - line.end.dx) / 3;
- // final bezierControlY = line.end.dy;
- final bifurcationX = line.start.dx < line.end.dx ? (line.end.dx - line.start.dx) / 2 : (line.start.dx - line.end.dx) / 2;
- final bifurcationPoint = line.start.dx < line.end.dx ? Offset(line.start.dx + bifurcationX, line.start.dy) : Offset(line.start.dx - bifurcationX, line.start.dy);
- final turnPoint = Offset(bifurcationPoint.dx, line.end.dy);
- // final rect = Rect.fromLTWH(turnPoint.dx, turnPoint.dy, 8, 8);
- // final startAngle = pi;
- // final sweepAngle = bifurcationPoint.dy > turnPoint.dy ? 0.5 * pi : -0.5 * pi;
- // final Path path = Path()
- // ..moveTo(line.start.dx, line.start.dy)
- // ..lineTo(bifurcationPoint.dx, bifurcationPoint.dy)
- // ..lineTo(turnPoint.dx, turnPoint.dy)
- // ..addArc(rect, startAngle, sweepAngle)
- // ..lineTo(line.end.dx, line.end.dy);
- //// ..quadraticBezierTo(bezierControlX, bezierControlY, line.end.dx, line.end.dy);
- // canvas.drawPath(path, myPaint);
- canvas.drawLine(line.start, bifurcationPoint, myPaint);
- canvas.drawLine(bifurcationPoint, turnPoint, myPaint);
- canvas.drawLine(turnPoint, line.end, myPaint);
- }
- }
- }
- @override
- bool shouldRepaint(CustomPainter oldDelegate) {
- // if(oldDelegate is MindMapPainter) {
- // // todo 这里有问题 每次oldDelegate里面的数据都没有变化
- // final thisMap = json.encode(this.root.toJson());
- // final oldMap = json.encode(oldDelegate.root.toJson());
- // final check = checkIsImageCacheChanged(oldDelegate.mindMapImages);
- // print('check:$check , size:${this.mindMapImages.length} , old:${oldDelegate.mindMapImages.length}');
- // if(thisMap == oldMap
- // && this.selectRect == oldDelegate.selectRect
- // && !check
- // && !checkLinesChanged(oldDelegate.linePaintElement)) {
- // return false;
- // }
- // }
- return this != oldDelegate;
- }
- ///
- /// 图片资源是否有变化
- ///
- bool checkIsImageCacheChanged(Map<String, ui.Image> oldMap) {
- if (mindMapImages.length != oldMap.length) {
- return true;
- }
- for(var url in mindMapImages.keys) {
- bool isInOldMap = false;
- for(var oldUrl in oldMap.keys) {
- if (url == oldUrl) {
- isInOldMap = true;
- }
- }
- if (!isInOldMap) {
- return true;
- }
- }
- return false;
- }
- bool checkLinesChanged(LinePaintElement oldlinePaint) {
- if(linePaintElement?.lines.length != oldlinePaint.lines.length) {
- return true;
- }
- if(linePaintElement?.style.style != oldlinePaint.style.style
- || linePaintElement?.style.color != oldlinePaint.style.color
- || linePaintElement?.style.strokeWidth != oldlinePaint.style.strokeWidth) {
- return true;
- }
- var list = linePaintElement?.lines ?? [];
- var oldlist = oldlinePaint.lines;
- for(var line in list) {
- bool isInOld = false;
- for(var oldline in oldlist) {
- if(line.start == oldline.start && line.end == oldline.end) {
- isInOld = true;
- }
- }
- if(!isInOld) {
- return true;
- }
- }
- return false;
- }
- }
|