Re: sync drawing an ever-increasing path

2012-10-23 Thread Roland King
hmm .. actually it looks like I can TOTALLY use CALayer for this. I need a 
better book, the one I have doesn't cover this. Hitting google. 


On 23 Oct, 2012, at 7:37 PM, Roland King r...@rols.org wrote:

 I want to animate the drawing of  CGPath in a UIView, so it looks as if it's 
 being drawn. I have the UIView, I have the CGPath, I am able to split the 
 CGPath at any point from 0 to 100% into that which should be drawn and that 
 which shouldn't yet, that's all done, so I can, fairly efficiently, call 
 -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] and get a path. 
 
 The idea is to call setNeedsDisplay on the UIView from time to time, then 
 figure out, when I get my -drawRect call how far through the animation I am, 
 call fractionalPath: for that fraction of the total animation time, and draw 
 it. The path isn't that complex, it doesn't take very long to draw and I'm 
 compositing already-fully-drawn paths into a backing UIImage so there's only 
 one 'live one' at any time. 
 
 The bit I'm not sure about is how to sync this up with the natural framerate 
 of the device. I could call setNeedsDisplay on a timer, or with a delay after 
 each drawRect, but there is surely a better way to do this, is there not? If 
 I do call setNeedsDisplay a lot, will I only get drawRect at most at the 
 natural framerate of the device. 
 
 Is there an obvious technology I'm missing? This is a pretty simple way to do 
 a quick animation of a single path, so OpenGL or anything like that is 
 massive overkill and I didn't see anything CALayer would give me which would 
 help, but wondered if I'd missed something there as that does have the 
 concept of animating a property, even a custom one, between two values and I 
 wondered if I could hook into that. 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 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:
 https://lists.apple.com/mailman/options/cocoa-dev/rols%40rols.org
 
 This email sent to r...@rols.org

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: sync drawing an ever-increasing path

2012-10-23 Thread David Duncan
On Oct 23, 2012, at 4:37 AM, Roland King r...@rols.org wrote:

 I want to animate the drawing of  CGPath in a UIView, so it looks as if it's 
 being drawn. I have the UIView, I have the CGPath, I am able to split the 
 CGPath at any point from 0 to 100% into that which should be drawn and that 
 which shouldn't yet, that's all done, so I can, fairly efficiently, call 
 -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] and get a path. 


You can do this with a CAShapeLayer by animating the strokeEnd property. Should 
be very simple to do, although if your path is very complex it may make more 
sense to break it into pieces and use multiple shape layers animated 
sequentially.
--
David Duncan


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: sync drawing an ever-increasing path

2012-10-23 Thread David Rowland
This worked for me. When initializing your UIView, add an instance variable 
shapeLayer and do this,

shapeLayer = [CAShapeLayer layer];
[[self layer] addSublayer:shapeLayer];


In drawRect, set up your path and do this,

CABasicAnimation *pathAnimation = [CABasicAnimation 
animationWithKeyPath:@strokeEnd];
pathAnimation.duration = 4.0;
pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
[shapeLayer addAnimation:pathAnimation forKey:@strokeEndAnimation];



That seems to be all that is needed.

David




On Oct 23, 2012, at 11:37 AM, David Duncan david.dun...@apple.com wrote:

 On Oct 23, 2012, at 4:37 AM, Roland King r...@rols.org wrote:
 
 I want to animate the drawing of  CGPath in a UIView, so it looks as if it's 
 being drawn. I have the UIView, I have the CGPath, I am able to split the 
 CGPath at any point from 0 to 100% into that which should be drawn and that 
 which shouldn't yet, that's all done, so I can, fairly efficiently, call 
 -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] and get a path. 
 
 
 You can do this with a CAShapeLayer by animating the strokeEnd property. 
 Should be very simple to do, although if your path is very complex it may 
 make more sense to break it into pieces and use multiple shape layers 
 animated sequentially.
 --
 David Duncan
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 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:
 https://lists.apple.com/mailman/options/cocoa-dev/rowlandd%40sbcglobal.net
 
 This email sent to rowla...@sbcglobal.net

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: sync drawing an ever-increasing path

2012-10-23 Thread David Duncan

On Oct 23, 2012, at 12:34 PM, David Rowland rowla...@sbcglobal.net wrote:

 This worked for me. When initializing your UIView, add an instance variable 
 shapeLayer and do this,
 
 shapeLayer = [CAShapeLayer layer];
 [[self layer] addSublayer:shapeLayer];
 
 
 In drawRect, set up your path and do this,

There is no need to do this inside of drawRect. In fact by doing so (unless 
your UIView actually needs to draw something) you've unnecessarily increased 
your memory footprint and reduce the performance to start the animation.

If you want the animation to happen as soon as the view is placed in the 
window, the correct place to do this is inside of -[UIView didMoveToWindow:]. 
Just check that the moved to window is not nil (or nothing will happen).

 
 CABasicAnimation *pathAnimation = [CABasicAnimation 
 animationWithKeyPath:@strokeEnd];
 pathAnimation.duration = 4.0;
 pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
 pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
 [shapeLayer addAnimation:pathAnimation forKey:@strokeEndAnimation];

You can also do this implicitly once the layer is in a layer tree by setting 
the animation duration on the current CATransaction and setting the strokeEnd 
directly.

 
 
 
 That seems to be all that is needed.
 
 David
 
 
 
 
 On Oct 23, 2012, at 11:37 AM, David Duncan david.dun...@apple.com wrote:
 
 On Oct 23, 2012, at 4:37 AM, Roland King r...@rols.org wrote:
 
 I want to animate the drawing of  CGPath in a UIView, so it looks as if 
 it's being drawn. I have the UIView, I have the CGPath, I am able to split 
 the CGPath at any point from 0 to 100% into that which should be drawn and 
 that which shouldn't yet, that's all done, so I can, fairly efficiently, 
 call -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] and get a path. 
 
 
 You can do this with a CAShapeLayer by animating the strokeEnd property. 
 Should be very simple to do, although if your path is very complex it may 
 make more sense to break it into pieces and use multiple shape layers 
 animated sequentially.
 --
 David Duncan
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 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:
 https://lists.apple.com/mailman/options/cocoa-dev/rowlandd%40sbcglobal.net
 
 This email sent to rowla...@sbcglobal.net
 

--
David Duncan

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: sync drawing an ever-increasing path

2012-10-23 Thread David Rowland
There are several paths to be animated. I want each to appear when the user 
does some action. It seemed the best to but them in a method called by drawRect 
and redraw the view when something changed. Why would the memory footprint be 
enlarged?

thanks for pointing to didMoveToWindow.

David



On Oct 23, 2012, at 1:25 PM, David Duncan david.dun...@apple.com wrote:

 
 On Oct 23, 2012, at 12:34 PM, David Rowland rowla...@sbcglobal.net wrote:
 
 This worked for me. When initializing your UIView, add an instance variable 
 shapeLayer and do this,
 
 shapeLayer = [CAShapeLayer layer];
 [[self layer] addSublayer:shapeLayer];
 
 
 In drawRect, set up your path and do this,
 
 There is no need to do this inside of drawRect. In fact by doing so (unless 
 your UIView actually needs to draw something) you've unnecessarily increased 
 your memory footprint and reduce the performance to start the animation.
 
 If you want the animation to happen as soon as the view is placed in the 
 window, the correct place to do this is inside of -[UIView didMoveToWindow:]. 
 Just check that the moved to window is not nil (or nothing will happen).
 
 
 CABasicAnimation *pathAnimation = [CABasicAnimation 
 animationWithKeyPath:@strokeEnd];
 pathAnimation.duration = 4.0;
 pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
 pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
 [shapeLayer addAnimation:pathAnimation forKey:@strokeEndAnimation];
 
 You can also do this implicitly once the layer is in a layer tree by setting 
 the animation duration on the current CATransaction and setting the strokeEnd 
 directly.
 
 
 
 
 That seems to be all that is needed.
 
 David
 
 
 
 
 On Oct 23, 2012, at 11:37 AM, David Duncan david.dun...@apple.com wrote:
 
 On Oct 23, 2012, at 4:37 AM, Roland King r...@rols.org wrote:
 
 I want to animate the drawing of  CGPath in a UIView, so it looks as if 
 it's being drawn. I have the UIView, I have the CGPath, I am able to split 
 the CGPath at any point from 0 to 100% into that which should be drawn and 
 that which shouldn't yet, that's all done, so I can, fairly efficiently, 
 call -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] and get a 
 path. 
 
 
 You can do this with a CAShapeLayer by animating the strokeEnd property. 
 Should be very simple to do, although if your path is very complex it may 
 make more sense to break it into pieces and use multiple shape layers 
 animated sequentially.
 --
 David Duncan
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 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:
 https://lists.apple.com/mailman/options/cocoa-dev/rowlandd%40sbcglobal.net
 
 This email sent to rowla...@sbcglobal.net
 
 
 --
 David Duncan
 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: sync drawing an ever-increasing path

2012-10-23 Thread David Duncan
On Oct 23, 2012, at 2:44 PM, David Rowland rowla...@sbcglobal.net wrote:

 There are several paths to be animated. I want each to appear when the user 
 does some action. It seemed the best to but them in a method called by 
 drawRect and redraw the view when something changed. Why would the memory 
 footprint be enlarged?

Because simply by implementing -drawRect:, your view will now consume 
pixelWidth * pixelHeight * 4 bytes of memory, and will need to be rendered onto 
the screen every time something changes.

You could do the exact same thing by just implementing an arbitrarily named 
method that you call instead of -setNeedsDisplay without the overhead.

 
 thanks for pointing to didMoveToWindow.
 
 David
 
 
 
 On Oct 23, 2012, at 1:25 PM, David Duncan david.dun...@apple.com wrote:
 
 
 On Oct 23, 2012, at 12:34 PM, David Rowland rowla...@sbcglobal.net wrote:
 
 This worked for me. When initializing your UIView, add an instance variable 
 shapeLayer and do this,
 
 shapeLayer = [CAShapeLayer layer];
 [[self layer] addSublayer:shapeLayer];
 
 
 In drawRect, set up your path and do this,
 
 There is no need to do this inside of drawRect. In fact by doing so (unless 
 your UIView actually needs to draw something) you've unnecessarily increased 
 your memory footprint and reduce the performance to start the animation.
 
 If you want the animation to happen as soon as the view is placed in the 
 window, the correct place to do this is inside of -[UIView 
 didMoveToWindow:]. Just check that the moved to window is not nil (or 
 nothing will happen).
 
 
 CABasicAnimation *pathAnimation = [CABasicAnimation 
 animationWithKeyPath:@strokeEnd];
 pathAnimation.duration = 4.0;
 pathAnimation.fromValue = [NSNumber numberWithFloat:0.0f];
 pathAnimation.toValue = [NSNumber numberWithFloat:1.0f];
 [shapeLayer addAnimation:pathAnimation forKey:@strokeEndAnimation];
 
 You can also do this implicitly once the layer is in a layer tree by setting 
 the animation duration on the current CATransaction and setting the 
 strokeEnd directly.
 
 
 
 
 That seems to be all that is needed.
 
 David
 
 
 
 
 On Oct 23, 2012, at 11:37 AM, David Duncan david.dun...@apple.com wrote:
 
 On Oct 23, 2012, at 4:37 AM, Roland King r...@rols.org wrote:
 
 I want to animate the drawing of  CGPath in a UIView, so it looks as if 
 it's being drawn. I have the UIView, I have the CGPath, I am able to 
 split the CGPath at any point from 0 to 100% into that which should be 
 drawn and that which shouldn't yet, that's all done, so I can, fairly 
 efficiently, call -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] 
 and get a path. 
 
 
 You can do this with a CAShapeLayer by animating the strokeEnd property. 
 Should be very simple to do, although if your path is very complex it may 
 make more sense to break it into pieces and use multiple shape layers 
 animated sequentially.
 --
 David Duncan
 
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 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:
 https://lists.apple.com/mailman/options/cocoa-dev/rowlandd%40sbcglobal.net
 
 This email sent to rowla...@sbcglobal.net
 
 
 --
 David Duncan
 
 

--
David Duncan

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: sync drawing an ever-increasing path

2012-10-23 Thread Roland King

On 24 Oct, 2012, at 2:37 AM, David Duncan david.dun...@apple.com wrote:

 On Oct 23, 2012, at 4:37 AM, Roland King r...@rols.org wrote:
 
 I want to animate the drawing of  CGPath in a UIView, so it looks as if it's 
 being drawn. I have the UIView, I have the CGPath, I am able to split the 
 CGPath at any point from 0 to 100% into that which should be drawn and that 
 which shouldn't yet, that's all done, so I can, fairly efficiently, call 
 -(CGPath)[ myObject fractionalPath:(CGFloat)fraction ] and get a path. 
 
 
 You can do this with a CAShapeLayer by animating the strokeEnd property. 
 Should be very simple to do, although if your path is very complex it may 
 make more sense to break it into pieces and use multiple shape layers 
 animated sequentially.
 --
 David Duncan
 

Thanks David, my shape is a bit complex for the strokeEnd property animation, I 
need to slowly and accurately 'trace' the outline of a path which has multiple 
elements and contains several closed paths. I already did the math to give me 
the first x% of the path, efficiently, even splitting any last bezier into a 
partial, so I'm happy with that bit, just needed to draw these partial and 
growing paths in sequence. Also I need the path to join correctly as it bends, 
so drawing it as one path, not different paths on different layers, is optimal. 

So I made a custom CALayer, gave it a 'percentage' property, made that 
@dynamic. I set needsDisplayForKey: to return YES for @percentage so I get 
the redraw calls and implemented drawInContext: so that it fetches 
self.percentage, gets the path for that percentage and draws it. This works. 
The one thing I had trouble with was getting the animation to start and animate 
between whatever percentage was and whatever I set it to, the UIViewController 
just does layer.percentage=1 and expects that to animate. Eventually I found 
actionForKey: and overrode that method to return a CABasicAnimation .. like this

-(idCAAction)actionForKey:(NSString*)key
{
if( [ key isEqualToString:@percentage ] )
{
CABasicAnimation *anim = [ CABasicAnimation 
animationWithKeyPath:@percentage ];
anim.duration = 2.0f;
anim.fromValue = [ self.presentationLayer valueForKey:key ];
// --- why oh why
return anim;
}
else
return  [ super actionForKey:key ]; 
}

Two things I don't understand here. 

First, why do I have to set the fromValue? I found without doing that, I don't 
get an animation, it just jumps instantly to the final point and draws the 
whole path? But the documentation for CABasicAnimation says that if fromValue, 
toValue and byValue are all nil, it should animate from the previous value of 
keypath to the new value, which is what I want, but doesn't do it. I got stuck 
on this for ages until I googled up an example showing how to get the current 
value off the presentation layer and set anim.fromValue, then it works. 

Secondly, [ self.presentationLayer valueForKey:@percentage ] gives me the 
current value of percentage, which I use for fromValue, fortunately I don't 
need to set toValue, that it manages to do itself, but if I did want the 'new' 
value of percentage, how could I get it at that point? I've tried the model 
layer and everything else I can think of. Is the 'new' value of percentage 
available at all at the point of actionForKey being called?. 

Or is actionForKey: the wrong place to return this animation? 



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com