• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Animation in Cocoa too slow? [was: Animation with CALayer?]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Animation in Cocoa too slow? [was: Animation with CALayer?]


  • Subject: Re: Animation in Cocoa too slow? [was: Animation with CALayer?]
  • From: Troy Stephens <email@hidden>
  • Date: Wed, 6 Feb 2008 16:46:36 -0800

On Feb 6, 2008, at 9:27 AM, alex wrote:
Hi there,

Thanks for this answer- From what I see below this looks like a technique to animate the change from one value to another (and the result being the width of the line animating).

I'm not sure if this will work for me- I was really looking for a way to simply draw a rectangle that represents the meter level. I don't want to animate this per se. Just the act of drawing the rectangle repeatedly is the animation. This gets called periodically and ideally should not interfere with user interaction. What I have now works but the CPU usage is too high for me and I worry that this will become more of an issue later. My testing has led me to blame calling setNeedsDisplay, then waiting for the event loop, then the drawRect call (and all the setup work around those calls).. All that seems too slow and complex compared to what I "used to" do...

What I want to do is have a timer or thread that looks at a value and draws a rectangle to represent it. Effectively I want to grab a CGContextRef and draw to it periodically without all the repeated setup work- for instance, create a transparent overlay view, grab its CGContextRef and then draw when I need to (outside the event loop). Is this still possible? Or recommended? I promise I won't draw more often than the refresh rate. :)

Yes, it's quite possible. If you just want a bar display that immediately updates each time the value changes, you can lock focus on the view and redraw immediately each time the value changes. e.g.:


if ([view lockFocusIfCanDraw]) {
NSRect bounds = [view bounds];
CGFloat y = bounds.origin.y + (level value from 0.0 to 1.0) * bounds.size.height;


[[NSColor blackColor] set];
NSRectFill(bounds));
[[NSColor greenColor] set];
NSRectFill(NSMakeRect(bounds.origin.x, bounds.origin.y, bounds.size.width, y - bounds.origin.y));


    [view unlockFocus];
}

How does Core Animation do its thing without hogging the CPU I wonder?

By virtue of a background render thread, that offloads much work to the GPU.


Troy

On Feb 5, 2008, at 12:53 PM, Bill Dudney wrote:

Hi Alex,

I have an example that was going to be part of the book but ended up not fitting in the flow of things (although I might end up adding it back) that shows how to animate something like your audio level meter. The app animates the width of a line changing but the secret sauce can be applied to the length of the audio meter. The secret sauce, 1 make sure to call setNeedsDisplay: when the audio value changes, 2 implement the defaultAnimationForKey: method to return the animation you want used with the audio value changes;

- (void)setDrawnLineWidth:(float)value {
   [self willChangeValueForKey:@"drawnLineWidth"];
   drawnLineWidth = value;
   [self.path setLineWidth:drawnLineWidth];
   [self setNeedsDisplay:YES];
   [self didChangeValueForKey:@"drawnLineWidth"];
}

+ (id)defaultAnimationForKey:(NSString *)key {
static CABasicAnimation *drawnLineWidthBasicAnimation = nil;
if ([key isEqualToString:@"drawnLineWidth"]) {
if (drawnLineWidthBasicAnimation == nil) {
drawnLineWidthBasicAnimation = [[CABasicAnimation alloc] init];
}
return drawnLineWidthBasicAnimation;
} else {
return [super defaultAnimationForKey:key];
}
}


Then when you change the audio level do something like this;

- (IBAction)setWidth:(id)sender {
   [[self animator] setDrawnLineWidth:[sender floatValue]];
}

This example uses simple cocoa stuff that you already know (except for the defaultAnimationForKey: method) so its quicker uptake than getting your head wrapped around drawing with CA (which is conceptually similar to appkit drawing but in details its quite different). If you want or need to go that route keep in mind that layers do not clip their sublayers by default and that you should call display only when the layer needs to be redrawn not during animation. The whole animation is done via the presentation and render tree layers and if you call display a lot it will kill performance because its got to push the content down onto the render layer too often.

Animating the slider could use a similar approach and look a lot like the 'turn on time machine' button in the time machine prefs panel.

HTH,

-bd-
http://bill.dudney.net/roller/objc

On Feb 5, 2008, at 1:30 PM, alex wrote:

Hi there,

Hopefully this is the right list for this question. I haven't found what I was looking for after searching the archives for the "right" way to animate some graphics using cocoa.

I'm trying to draw two different things. One of them is an audio level meter and the other is an effect similar to what the iPhone "slide" graphic does on the lock screen on the iPhone.
(I have a mask that I slide a white blob around behind.)


I'm able to do both with an NSTimer that fires and then I issue a [setNeedsDisplay] from the timer to update the animation. This works fine and produces the expected results but seems to use way too much CPU compared to what I've been able to do "back in the day" using straight CG or worse Quickdraw. (I am not porting this code from QD- I threw that code away, this is all new code.)

I've been looking at using CALayers to implement the drawing so that I can call [display] rather than [setNeedsDisplay] with the hopes that this would make the animations use less CPU.

What is the right way to approach this problem? (and please don't suggest using Shark to optimize my code as that is a given and will be done after I determine what the best course of code will be).

thanks,
alex

_______________________________________________

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


_______________________________________________

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


--
Troy Stephens
Cocoa Frameworks
Apple, Inc.



_______________________________________________

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


  • Follow-Ups:
    • Re: Animation in Cocoa too slow? [was: Animation with CALayer?]
      • From: alex <email@hidden>
References: 
 >Animation with CALayer? (From: alex <email@hidden>)
 >Re: Animation with CALayer? (From: Bill Dudney <email@hidden>)
 >Animation in Cocoa too slow? [was: Animation with CALayer?] (From: alex <email@hidden>)

  • Prev by Date: Re: Core Data, NSURLProtocol and Threads - A Case of Missing Managed Objects
  • Next by Date: Searching for "whole word" in NSString
  • Previous by thread: Animation in Cocoa too slow? [was: Animation with CALayer?]
  • Next by thread: Re: Animation in Cocoa too slow? [was: Animation with CALayer?]
  • Index(es):
    • Date
    • Thread