Re: Animation in Cocoa too slow? [was: Animation with CALayer?]
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: Thu, 7 Feb 2008 11:25:24 -0800
On Feb 6, 2008, at 7:26 PM, alex wrote
This is the perfect answer!! Thank you.
One more question (sorry):
How would one approach doing this exact thing with Layers? Or is
that not recommended and it should be done in the view like below?
This could certainly be done using layers -- but if you aren't already
using Core Animation-based rendering in your UI for other reasons, I'd
recommend sticking with the plain NSView approach, as a CA renderer is
an awfully big hammer to bring in just to draw a simple set of moving
level bars.
If you did go the layer-based route, an efficient approach would be to
create a layer for each level bar, whose content was provided as a
CGImage or as a backgroundColor (which can be a solid or pattern
color), and change the layer's bounds height (or width) when the level
value changes. To suppress the default implicit layer bounds
animation so as to get an immediate response to level changes, you'd
make the change inside a CATransaction within which you disable actions:
[CATransaction begin];
[CATransaction setValue:[NSNumber numberWithBool:YES]
forKey:kCATransactionDisableActions];
levelLayer.bounds = CGRectMake(0, 0, LEVEL_BAR_WIDTH,
heightForNewLevelValue);
[CATransaction commit];
Providing the layer content as described effectively allows the redraw
work to be offloaded to the GPU, which should result in good
performance.
Troy
On Feb 6, 2008, at 4:46 PM, Troy Stephens wrote:
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
_______________________________________________
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