Re: Layer needs display if presentation layer moves?
Re: Layer needs display if presentation layer moves?
- Subject: Re: Layer needs display if presentation layer moves?
- From: Kyle Sluder <email@hidden>
- Date: Wed, 29 Jan 2014 12:14:04 -0800
On Wed, Jan 29, 2014, at 11:44 AM, Seth Willits wrote:
>
> - ConnectionsLayer has a private property: @property int
> nodePositionsDidChange;
> - +needsDisplayForKey: returns YES for "nodePositionsDidChange" (calls
> super for anything else)
> - noteNodePositionsChanged calls:
> [self addAnimation:[CABasicAnimation animationWithKeyPath:@"nodePositionsDidChange"] forKey:@"animateForNodePositionsChange"];
>
>
> The nodePositionsDidChange property itself is never set or get. It's
> simply there so that we can "animate" it, and Core Animation will
> recognize (via +needsDisplayForKey :) that while this property is
> animating, the layer should be redisplayed. Boom. (It's a bit voodoo that
> it can animate even though the value doesn't change at all, but there you
> go.)
>
>
>
> The only "negative" part to this approach is that even if none of the
> boxes change positions, if noteNodePositionsChanged is called then it
> will redraw many times for whatever the duration of the animation is. So
> for efficiency's sake, noteNodePositionsChanged should only be called if
> a box's position actually did change. Ideally, we wouldn't need to call
> noteNodePositionsChanged manually at all.
Interesting that you chose this approach. I haven't gotten around to
writing it up yet, but the past day or so of thinking through the
problem, but I was coming to the conclusion that the only way to get
this to work reliably would be to not rely on implicit animations at
all.
Instead, when you wanted to animate the subtree, you'd need to add
explicit CAAnimations to the entire tree.
//begin
@implementation MyView
- (void)animateLayerTree {
[CATransaction begin];
// Generate a CALayer -> NSValue(CGPoint) map
NSDictionary *sublayerToPositionMap = [self
_generateMapOfSublayersToNewPositions];
CAAnimationGroup *connectionsAnimGroup = [CAAnimationGroup animation];
for (CALayer *sublayer in sublayerToPositionMap.allKeys) {
CGPoint oldPosition = sublayer.position;
CGPoint newPosition = [sublayerToPositionMap
objectForKey:sublayer].pointValue;
sublayer.position = newPosition;
CGPoint oldConnectionEndpoint = [_connectionsLayer
convertPoint:oldPosition fromLayer:sublayer];
CGPoint newConnectionEndpoint = [_connectionsLayer
convertPoint:newPosition fromLayer:sublayer];
[connectionsAnimGroup addAnimation:[MyConnectionsAnimation
animationOfLineNamed:sublayer.name
fromPoint:oldConnectionEndpoint toPoint:newConnectionEndpoint];
}
// The connections layer returns YES for
+needsDisplayForKey:@"connections"
// TODO: Support retargeting animations mid-flight
[_connectionsLayer addAnimation:connectionsAnimGroup
forKey:@"connections"];
[CATransaction commit];
}
//end
This at least avoids the possibility that CA might stop sending
-setNeedsDisplay for a key which never changes, and it feels less
"magic".
--Kyle Sluder
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden