如何创建一个显示具有可移动节点的图形的 UIView?
How to create a UIView that shows a graph with moveable nodes?
注意这里的"graph"是图论图,不是统计图
我正在尝试创建一个图表,其中包含您可以在屏幕上四处移动的节点。我决定使用自定义 UIView
subclass - NodeView
来表示节点。为了让它可以移动,我使用了 CocoaPod SEDraggable.
我决定整个图表将由另一个名为 GraphView
的习俗 UIView
绘制。这个 class 有一个 graph
属性 并且设置后,它将通过首先从先前的图形(如果有的话)中删除子视图然后添加新的 NodeView
来绘制整个图形秒。然后我会调用 setNeedsDisplay
,后者又会调用 draw(_:)
.
在覆盖的 draw
方法中,我将在节点之间绘制线(边,在图论术语中)。
现在我需要检测一个节点被移动了。当它们被移动后,我需要调用 setNeedsDisplay
来重新绘制线条。我环顾四周,明白这可以用 KVO 来完成。但是,我的图形视图需要能够显示具有任意数量节点的图形。这意味着我会将我的节点放入一个数组中。根据这个 post,KVOing 数组是不可能的。
然后我尝试使用 NSNotificationCenter
,但我很快发现当视图从 post 移动时没有通知。
然后我发现了这个 post 但 OP 使用 KVO,由于上述原因不能用于我的情况。另外,那个post在Objective-C里面,我不是很懂。
如何创建这样的图表?我正朝着正确的方向前进吗?或者有没有我可以使用的技巧,它不涉及在移动节点时重绘所有内容?感觉每帧重画整个图会很慢
我发现我可以用 CADisplayLink
做到这一点。我没有在 NodeView
移动时重新绘制线条,而是每帧重新绘制它们。
// displayLink is a property of the GraphView class
displayLink = CADisplayLink(target: self, selector: #selector(updateNodePositions))
displayLink.add(to: .main, forMode: .defaultRunLoopMode)
// ...
@objc func updateNodePositions() {
// nodeViewsToNodes is a dictionary storing all the NodeViews as keys
// and the corresponding Node (my model object) as values. So here
// I am basically updating the model based on the view's positions
for kvp in nodeViewsToNodes {
kvp.value.x = kvp.key.frame.midX
kvp.value.y = kvp.key.frame.midY
}
setNeedsDisplay()
}
draw(_:)
方法会根据模型绘制线条。
注意这里的"graph"是图论图,不是统计图
我正在尝试创建一个图表,其中包含您可以在屏幕上四处移动的节点。我决定使用自定义 UIView
subclass - NodeView
来表示节点。为了让它可以移动,我使用了 CocoaPod SEDraggable.
我决定整个图表将由另一个名为 GraphView
的习俗 UIView
绘制。这个 class 有一个 graph
属性 并且设置后,它将通过首先从先前的图形(如果有的话)中删除子视图然后添加新的 NodeView
来绘制整个图形秒。然后我会调用 setNeedsDisplay
,后者又会调用 draw(_:)
.
在覆盖的 draw
方法中,我将在节点之间绘制线(边,在图论术语中)。
现在我需要检测一个节点被移动了。当它们被移动后,我需要调用 setNeedsDisplay
来重新绘制线条。我环顾四周,明白这可以用 KVO 来完成。但是,我的图形视图需要能够显示具有任意数量节点的图形。这意味着我会将我的节点放入一个数组中。根据这个 post,KVOing 数组是不可能的。
然后我尝试使用 NSNotificationCenter
,但我很快发现当视图从 post 移动时没有通知。
然后我发现了这个 post 但 OP 使用 KVO,由于上述原因不能用于我的情况。另外,那个post在Objective-C里面,我不是很懂。
如何创建这样的图表?我正朝着正确的方向前进吗?或者有没有我可以使用的技巧,它不涉及在移动节点时重绘所有内容?感觉每帧重画整个图会很慢
我发现我可以用 CADisplayLink
做到这一点。我没有在 NodeView
移动时重新绘制线条,而是每帧重新绘制它们。
// displayLink is a property of the GraphView class
displayLink = CADisplayLink(target: self, selector: #selector(updateNodePositions))
displayLink.add(to: .main, forMode: .defaultRunLoopMode)
// ...
@objc func updateNodePositions() {
// nodeViewsToNodes is a dictionary storing all the NodeViews as keys
// and the corresponding Node (my model object) as values. So here
// I am basically updating the model based on the view's positions
for kvp in nodeViewsToNodes {
kvp.value.x = kvp.key.frame.midX
kvp.value.y = kvp.key.frame.midY
}
setNeedsDisplay()
}
draw(_:)
方法会根据模型绘制线条。