I am creating a flow chart and when user drags a node, I want to move the line connected to it. In pan handler event of the node I implemented a CGAffineTransform
to transform line, but it does not move line smoothly. Any idea how other flow chart apps handle this problem?
func panHandler(sender: UIPanGestureRecognizer) {
else if (sender.state == .Changed)
{
let translation = sender.translationInView(self)
sender.view!.center = CGPointMake(originalCenter.x + translation.x, originalCenter.y + translation.y)
//rv is the connected line, created at an other place like:
//let w = GraphViewController.calcLength(e.x, y0: e.y, x1: e2.x, y1: e2.y)
//rv = UIView(frame: CGRectMake(0, 0, CGFloat(w), 1.0))
//var angle = GraphViewController.calcAngle(e.x, y0: e.y, x1: e2.x, y1: e2.y)
//rv.transform = CGAffineTransformMakeRotation(CGFloat(angle))
var angle = GraphViewController.calcAngle(e!.x, y0: e!.y, x1: r.destination!.x, y1:r.destination!.y)
rv!.transform = CGAffineTransformMakeRotation(CGFloat(angle))
}
}
Because you don't need any touch events on the line, we could use a plain CAShapeLayer
and update its path on pan. I assume you want to have some anchor point for the line.
Define some anchor point for your line
endOfLineAnchor = CGPoint(x: view.bounds.width / 2, y: view.bounds.height * 0.8)
Create some view to attach it to
ballView = createBallView()
ballView.center = CGPoint(x: view.bounds.width / 2, y: view.bounds.height / 2)
Add layer & view
lineLayer = CAShapeLayer()
lineLayer.strokeColor = UIColor.blackColor().CGColor
lineLayer.path = pathFromBallToAnchor()
view.layer.addSublayer(lineLayer)
view.addSubview(ballView)
On pan update the layer's path
else if (sender.state == .Changed)
{
let translation = sender.translationInView(self.view)
sender.view!.center = CGPointMake(originalCenter.x + translation.x, originalCenter.y + translation.y)
CATransaction.begin()
CATransaction.setValue(kCFBooleanTrue, forKey: kCATransactionDisableActions)
lineLayer.path = pathFromBallToAnchor()
CATransaction.commit()
}
the reason for the CATransaction
is that we want to disable implicit animations.
Construct the path:
func pathFromBallToAnchor() -> CGPathRef {
var bazier = UIBezierPath()
bazier.moveToPoint(ballView.center)
bazier.addLineToPoint(endOfLineAnchor)
return bazier.CGPath
}
the result: