Skip to content

Commit

Permalink
feat/refact: supported customize edge/vertex ui.
Browse files Browse the repository at this point in the history
  • Loading branch information
CorvusYe committed Jan 29, 2023
1 parent 80dab4c commit 8542051
Show file tree
Hide file tree
Showing 16 changed files with 207 additions and 75 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 0.0.1+7
- feat: supported customize vertex ui.
- feat: supported customize edge ui.

## 0.0.1+6
- Data panel embedding. ( For edge )
Expand Down
6 changes: 4 additions & 2 deletions README-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ void main() {
convertor: MapConvertor(),
options: Options()
..edgePanelBuilder = edgePanelBuilder
..vertexPanelBuilder = vertexPanelBuilder,
..vertexPanelBuilder = vertexPanelBuilder
..edgeShape = EdgeLineShape() // default is EdgeLineShape.
..vertexShape = VertexCircleShape(), // default is VertexCircleShape.
),
),
));
Expand Down Expand Up @@ -115,7 +117,7 @@ Widget vertexPanelBuilder(hoverVertex) {
return Stack(
children: [
Positioned(
left: hoverVertex.cpn!.position.x + hoverVertex.cpn!.radius + 5,
left: hoverVertex.cpn!.position.x + hoverVertex.radius + 5,
top: hoverVertex.cpn!.position.y - 20,
child: SizedBox(
width: 120,
Expand Down
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ void main() {
convertor: MapConvertor(),
options: Options()
..edgePanelBuilder = edgePanelBuilder
..vertexPanelBuilder = vertexPanelBuilder,
..vertexPanelBuilder = vertexPanelBuilder
..edgeShape = EdgeLineShape() // default is EdgeLineShape.
..vertexShape = VertexCircleShape(), // default is VertexCircleShape.
),
),
));
Expand Down Expand Up @@ -115,7 +117,7 @@ Widget vertexPanelBuilder(hoverVertex) {
return Stack(
children: [
Positioned(
left: hoverVertex.cpn!.position.x + hoverVertex.cpn!.radius + 5,
left: hoverVertex.cpn!.position.x + hoverVertex.radius + 5,
top: hoverVertex.cpn!.position.y - 20,
child: SizedBox(
width: 120,
Expand Down
3 changes: 2 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ void main() {
options: Options()
..edgePanelBuilder = edgePanelBuilder
..vertexPanelBuilder = vertexPanelBuilder
..shape = CircleShape(), // default is CircleShape.
..edgeShape = EdgeLineShape() // default is EdgeLineShape.
..vertexShape = VertexCircleShape(), // default is VertexCircleShape.
),
),
));
Expand Down
2 changes: 1 addition & 1 deletion lib/core/algorithm/force_directed.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class ForceDirected extends GraphAlgorithm {
}

// Keep children vertexes around the parent vertex.
if (v.prevVertex != null && !v.hover) {
if (v.prevVertex != null && !v.isHovered) {
if (Util.distance(v.position, v.prevVertex!.position) <
5 * v.prevVertex!.radius) {
v.position += (v.position - v.prevVertex!.position) / 100;
Expand Down
11 changes: 8 additions & 3 deletions lib/core/options.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ class Options {
/// 边数据面板的构建器,鼠标悬停到对应节点时触发。
Widget Function(Edge hoverVertex)? edgePanelBuilder;

/// set shape strategy for components of vertex or edge.
/// set shape strategy for components of vertex.
///
/// 给点跟边设置形状
OptionShape shape = CircleShape();
/// 给点设置形状
VertexShape vertexShape = VertexCircleShape();

/// set shape strategy for components of edge.
///
/// 给边设置形状
EdgeShape edgeShape = EdgeLineShape();
}
34 changes: 34 additions & 0 deletions lib/core/options/shape/edge/edge_line_shape.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2023- All flutter_graph_view authors. All rights reserved.
//
// This source code is licensed under Apache 2.0 License.

import 'package:flutter/material.dart';
import 'package:flutter_graph_view/flutter_graph_view.dart';

/// The default edge shape impl.
///
/// 默认使用 直线做边。
class EdgeLineShape extends EdgeShape {
@override
render(Edge edge, Canvas canvas, Paint paint, List<Paint> paintLayers) {
paint.strokeWidth = edge.isHovered ? 3 : 1;

var startPoint = Offset.zero;
var endPoint = Offset(len(edge), 0);
canvas.drawLine(startPoint, endPoint, paint);
}

@override
void setPaint(Edge edge) {
if (isWeaken(edge)) {
edge.cpn!.paint = Paint()..color = Colors.white.withOpacity(0);
} else {
edge.cpn!.paint = Paint()..color = Colors.white;
}
}

@override
double height(Edge edge) {
return 1.0;
}
}
77 changes: 77 additions & 0 deletions lib/core/options/shape/edge_shape.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright (c) 2023- All flutter_graph_view authors. All rights reserved.
//
// This source code is licensed under Apache 2.0 License.

import 'dart:ui';

import 'package:flutter_graph_view/core/util.dart';
import 'package:flutter_graph_view/flutter_graph_view.dart';

/// Used to customize the edge UI.
///
/// 用于自定义边的UI
abstract class EdgeShape {
/// render the edge shape to canvas by data.
///
/// 通过边数据将自定义的图形绘制到画布中。
render(Edge edge, Canvas canvas, Paint paint, List<Paint> paintLayers);

/// compute the width of the shape from data, used for overlap and mouse event judgment.
///
/// 通过数据来计算形状的宽,用于重叠与鼠标事件判断。
double width(Edge edge) {
return len(edge);
}

/// compute the height of the shape from data, used for overlap and mouse event judgment.
///
/// 通过数据计算形状的高,用于重叠与鼠标事件判断。
double height(Edge edge);

/// compute the size of the shape from data, used for overlap and mouse event judgment.
///
/// 通过数据计算形状的尺寸,用于重叠与鼠标事件判断。
Vector2 size(Edge edge) {
return Vector2(width(edge), height(edge));
}

/// update the paint from data.
///
/// 根据数据更新画笔属性。
void setPaint(Edge edge);

/// When some elements are activated and do not contain the current element.
///
/// 当一些元素被激活且不包含当前元素
bool isWeaken(Edge edge) {
var graph = edge.cpn!.gameRef.graph;
return graph.hoverVertex != null &&
!graph.hoverVertex!.neighborEdges.contains(edge);
}

/// Compute the line length by two vertex.
///
/// 通过两个节点的坐标,计算线的长度。
double len(Edge edge) =>
edge.end == null || edge.start.cpn == null || edge.end!.cpn == null
? 10
: Util.distance(edge.start.cpn!.position, edge.end!.cpn!.position);

/// Compute the shape angle by two vertex.
///
/// 通过两个节点的坐标,获取线的旋转角度
double angle(Edge edge) {
Offset offset = Offset(
(edge.end == null
? edge.start.cpn!.position.x
: edge.end!.cpn!.position.x) -
(edge.start.cpn!.position.x),
(edge.end == null
? edge.start.cpn!.position.y
: edge.end!.cpn!.position.y) -
(edge.start.cpn!.position.y),
);

return offset.direction;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import 'package:flutter_graph_view/flutter_graph_view.dart';
/// The default shape impl.
///
/// 默认使用 圆型做节点。
class CircleShape implements OptionShape {
class VertexCircleShape extends VertexShape {
@override
render(Vertex vertex, Canvas canvas, paint, paintLayers) {
canvas.drawCircle(
Expand Down Expand Up @@ -48,10 +48,7 @@ class CircleShape implements OptionShape {
@override
void setPaint(Vertex vertex) {
var cpn = vertex.cpn!;
var graph = cpn.gameRef.graph;
if (graph.hoverVertex != null &&
(vertex != graph.hoverVertex &&
!graph.hoverVertex!.neighbors.contains(vertex))) {
if (isWeaken(vertex)) {
cpn.paint = Paint()
..shader = Gradient.radial(
Offset(vertex.radius, vertex.radius),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import 'dart:ui';
import 'package:flame/collisions.dart';
import 'package:flutter_graph_view/flutter_graph_view.dart';

/// Used to customize the vertex UI. Maybe the UI of the edge will also use this.
/// Used to customize the vertex UI.
///
/// 用于自定义节点的UI,可能边的定制也会用这个接口,待定
abstract class OptionShape {
/// render the shape by canvas.
/// 用于自定义节点的UI。
abstract class VertexShape {
/// render the vertex shape to canvas by data.
///
/// 通过Canvas绘制自定义的图形
/// 通过节点数据将自定义的图形绘制到画布中
render(Vertex vertex, Canvas canvas, Paint paint, List<Paint> paintLayers);

/// compute the width of the shape from data, used for overlap and mouse event judgment.
Expand All @@ -26,6 +26,13 @@ abstract class OptionShape {
/// 通过数据计算形状的高,用于重叠与鼠标事件判断。
double height(Vertex vertex);

/// compute the size of the shape from data, used for overlap and mouse event judgment.
///
/// 通过数据计算形状的尺寸,用于重叠与鼠标事件判断。
Vector2 size(Vertex vertex) {
return Vector2(width(vertex), height(vertex));
}

/// create a hit box, used for overlap judgment.
///
/// 创建一个碰撞容器,用于碰撞检测,解决重叠问题。
Expand All @@ -40,4 +47,15 @@ abstract class OptionShape {
///
/// 根据数据更新画笔属性。
void setPaint(Vertex vertex);

/// When some elements are activated and do not contain the current element.
///
/// 当一些元素被激活且不包含当前元素
bool isWeaken(Vertex vertex) {
var cpn = vertex.cpn!;
var graph = cpn.gameRef.graph;
return graph.hoverVertex != null &&
(vertex != graph.hoverVertex &&
!graph.hoverVertex!.neighbors.contains(vertex));
}
}
6 changes: 4 additions & 2 deletions lib/flutter_graph_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ export 'package:flutter_graph_view/core/convertor/map_convertor.dart';
/// core interfaces
export 'core/options.dart';
export 'core/graph_algorithm.dart';
export 'core/option_shape.dart';
export 'core/options/shape/vertex_shape.dart';
export 'core/options/shape/edge_shape.dart';

/// interfaces' default impl
export 'core/algorithm/force_directed.dart';
export 'core/shape/circle_shape.dart';
export 'core/options/shape/vertex/vertex_circle_shape.dart';
export 'core/options/shape/edge/edge_line_shape.dart';

/// third party
export 'package:flame/flame.dart';
Expand Down
19 changes: 17 additions & 2 deletions lib/model/edge.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,47 @@ import 'dart:ui';

import 'package:flutter_graph_view/flutter_graph_view.dart';

///
/// Data model of edge component.
/// 关系【边】组件的数据模型
///
/// 关系【边】组件的数据模型
class Edge {
/// The key for edge.
///
/// 关系键
late int ranking;

/// The name of edge.
///
/// 关系名
late String edgeName;

/// Edge data, will display in panel by hover callback.
///
/// 关系的原始数据,将通过回调展示在自定义面板上
late dynamic data;

/// Cache the source vertex.
///
/// 对当前关系的起始节点进行缓存
late Vertex start;

/// Cache the destination vertex.
///
/// 对当前关系的终止节点进行缓存
Vertex? end;

/// Cache the colors for this edge.
///
/// 颜色放置器,用于缓存当前关系所需使用到的颜色
late List<Color> colors;

/// cache the component for edge model.
///
/// 边模型缓存其对应的组件元素
EdgeComponent? cpn;

/// Is this edge under focus now
///
/// 当前边是否有鼠标浮入
bool get isHovered => cpn?.isHovered ?? false;
}
15 changes: 11 additions & 4 deletions lib/model/vertex.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,6 @@ class Vertex<I> {
radius = (math.log(degree * 10 + 1)) + 8;
}

/// Is this vertex under focus now
/// 当前节点是否有鼠标浮入
bool hover = false;

/// Whether this vertex being picked.
bool picked = false;

Expand Down Expand Up @@ -102,4 +98,15 @@ class Vertex<I> {
Vertex();

VertexComponent? cpn;

/// Is this vertex under focus now
///
/// 当前节点是否有鼠标浮入
@Deprecated("will remove in v0.0.2. use isHovered insteads of")
bool hover = false;

/// Is this vertex under focus now
///
/// 当前节点是否有鼠标浮入
bool get isHovered => cpn?.isHovered ?? false;
}
Loading

0 comments on commit 8542051

Please sign in to comment.