4

Using core animation layers, I've been trying to implement the following feature. Within a containing superlayer, there are two anchor layers, and another layer that connects the two. The following image should make the situation clear. On the left, the two orange-coloured anchors are marked 'A' and 'B', and the green line connects them. The enclosing layer frames are shown using dotted lines. On the right, the layer hierarchy is shown as I've currently implemented it, where both the anchors and the connection are sublayer of the enclosing superlayer. Connected core animation layers scheme

Now, what I'm trying to do is allow the anchors to be moved around, and have the connection stay attached. I'm currently updating its frame and path properties exploiting the connection layer's -setFrame: method , using the code shown below:

- (void)setFrame:(CGRect)frame {

CGSize size = frame.size;
CGPoint startPoint = CGPointZero;
if (size.height < 0.0) startPoint.y -= size.height;

CGPathRef oldPath = self.path;
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, startPoint.x, startPoint.y);
CGPathAddLineToPoint(path, NULL, startPoint.x + size.width, startPoint.y + size.height);

CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.duration = [CATransaction animationDuration];
animation.timingFunction = [CATransaction animationTimingFunction];
animation.fromValue = (id)oldPath;
animation.toValue = (id)path;
[self addAnimation:animation forKey:@"pathAnimation"];

self.path = path;
CGPathRelease(path);
[super setFrame:frame];

}

Now, this sort of works, but the problem is that the frame (or position + bounds) animation doesn't run in sync with the path animation, causing some jittery effects where the connection's far end momentarily detaches (and some other minor issues to, presumably caused by the same core issue).

I've been toying around with the issue, but only to moderate success. At one point, I set the connection's frame equal to that of the enclosing superlayer, which did have the desired effect (since now the frame doesn't need to be animated any longer). However, I'm worried about the performance of this solution in a context with multiple connections—ie. multiple non-opaque, large-size overlapping layers seems bad?

Would anyone have a better, more elegant solution to this? Thanks!

2 Answers2

1

Since you're only really stretching (scaling) and rotating the connection layer have you considered applying transformations to it instead of manually modifying the frame?

You should be able to calculate the angle of rotation and scaling factor using some basic trigonometry based on the positions of the anchor layers.

mjisrawi
  • 7,846
  • 3
  • 24
  • 27
  • Hmmm, wouldn't that distort the shape layer's path, with eg. line width scaling anisotropically? Please note that the problem as posed is simplified, and in reality I'm using Bézier-curve paths. – Bastiaan M. van de Weerd Aug 17 '11 at 10:29
  • CAShapeLayers are vector based, so there should be no distortion. It should work with Bezier Curve paths as well. – mjisrawi Aug 17 '11 at 10:49
  • I'll give it a shot. Still, would you be able to tell me anything about the performance issue I pointed out? – Bastiaan M. van de Weerd Aug 17 '11 at 10:58
  • I'm not sure how it would compare performance-wise, I mentioned transformations since I've used them in the path with no performance issues. – mjisrawi Aug 17 '11 at 11:11
  • Your solution does work, for future reference. However, it's only suitable when the path is scaled linearly, which is not the case in my situation (eg. I handle edge cases where anchor B is to the left of or above anchor A differently.) In the end, though, the solution is similar to what I mentioned in my original post in that you make the shape layer frame a constant, and only touch either the shape itself or the transformation. I'm still curious if there are other solutions. – Bastiaan M. van de Weerd Aug 17 '11 at 20:40
0

Since you are animating the path and not the frame of the layer or path, you will get performance issues after approx. 50 simultaneous animations. You will achieve high performance only when manipulating the layers implicit animatable properties, therefore its frame and not its content (e.g path), because of gpu acceleration.

Pascalius
  • 14,024
  • 4
  • 40
  • 38