PDA

View Full Version : How do I make a spot glow?




pflau
Aug 5, 2010, 02:00 PM
Hi. I am a total newbie to graphics on Core Graphics and OpenGL. I only had some experience with Windows graphics - bitblitz, metafile, and so on. So what is the most straight forward way to make a shape glow on a view? For instance, if I want to write an app where if you touch a spot on the screen, the spot would glow, and when you remove your finger, the spot would gradually dim and turn invisible. What is the most straight forward way to do that? I'm asking because I don't want to set off on the wrong track. Thank you!



PhoneyDeveloper
Aug 5, 2010, 04:14 PM
I haven't tried this but here are some links

Glow effect for a UILabel

http://forums.pragprog.com/forums/57/topics/1183

Glow effect for any text

http://stackoverflow.com/questions/1229721/is-there-an-easy-way-or-library-available-to-let-text-glow/1230907#1230907

Glow effect google search

http://www.google.com/search?hl=en&as_q=iphone+glow+effect&as_epq=&as_oq=&as_eq=&num=100&lr=&as_filetype=&ft=i&as_sitesearch=&as_qdr=all&as_rights=&as_occt=any&cr=&as_nlo=&as_nhi=&safe=off

The Glow effect for any text can also be used I think to make any Quartz drawing glow, or of course you could draw a dot under the user's finger tip. This Glow effect that's built into Quartz makes the glow appear but doesn't make it disappear. You would want to draw your glow into a view and then fade out the view with an alpha fade to zero.

pflau
Aug 6, 2010, 03:01 PM
Hi. Thanks for the suggestion. My goal is actually a little bit more than just make a label or button glow. My goal is to create a touchpad that gives the user feedback on their touches. One thing I have in mind is that when the user makes a pinch gesture, there would be a glowing ring expanding and contracting following the user's two fingers. So what it means is I probably would need to render the shape in real time, and apply the glow effect in real time.

But before I do that, I ran into a problem already. I want to do the effect from the view controller and not the drawRect function. How do I get the view's graphic context from the controller? How does UIKit create a context for the drawRect function?

pflau
Aug 6, 2010, 03:33 PM
OK, I no longer need to get the context from the controller because I applied my experience programming for Windows and realized the key is to invalidate the region to force a redraw by the framework. I called setNeedsDisplayInRect to force drawRect to be called.

PhoneyDeveloper
Aug 6, 2010, 05:23 PM
If your goal is to have a glowing line that follows the touch this needs to be handled mostly in a custom view. Almost always if you're calling [somethingElse setNeedsDisplay] you are making a mistake. It should be [self setNeedsDisplay]. The view can notify its view controller about things that are happening with a delegate callback, but don't put the guts of this in a view controller. The way that touches are handled may also require that a lot of your logic is in the view.

Anyway, what you describe is somewhat complicated and involves keeping some state about the previous actions of the touch. This will be somewhat hard to make work. Much more than simply making something glow.

pflau
Aug 6, 2010, 05:40 PM
Since I override drawRect, I pretty much have a custom view.

The reason I put the logic in the controller is that the controller is what is handling all the gestures and is the only object who knows what the view needs to display. The view itself has absolutely no clue - after all it is just a view that displays whatever it is told. I think this follows the MVC paradigm.

I make use of GestureRecognizer and it seems Apple's sample code always make the controller the target (delegate) and not the view.

But ultimately it works both ways, since the view has a pointer to the controller anyway.

pflau
Aug 6, 2010, 06:35 PM
Actually I might not need a "glow" effect, what I might need is a shape that is drawn by a soft brush, such as a brush in Photoshop where the line edge is always soft. If I can find such a brush I only need to outline a shape with the soft brush and fill in the middle with solid color. And I can then play with transparency and fade effect if I can find them.

pflau
Aug 7, 2010, 03:51 PM
Well it seems I've given up on CoreGraphics and decided to just get my hands dirty with CoreAnimation. I've had some success with using CALayer to render some effect. I think that is definitely the way to go.

pflau
Aug 8, 2010, 10:52 PM
OK, at this point I think I can say that I have found a solution to my original question. For the benefit of the net (since I couldn't Google any answer) here is what I did:

First I simply created a PNG file using Adobe. The PNG file contains a circle processed with 24 pixels of Gaussian blur on a transparent background. So basically I gave up trying to create a good looking glowing circle on the fly and manually drew one. This is the easy part.

The next part is to make the circle appear very fast, and then gradually fade out.

To do that I create a CALayer that contains the circle. This is the code from the awakeFromNib of my custom view:


const char* fileName = [[[NSBundle mainBundle] pathForResource:@"CircleBlur" ofType:@"png"] UTF8String];
CGDataProviderRef data_ref = CGDataProviderCreateWithFilename(fileName);

CGImageRef theImage = CGImageCreateWithPNGDataProvider(data_ref, NULL, NO, kCGRenderingIntentDefault);
touch_one_layer=[CALayer layer];
touch_one_layer.contents=theImage;
touch_one_layer.bounds=CGRectMake(0.0f,0.0f,90.0f,90.0f);
touch_one_layer.opacity=0;
[[self layer] addSublayer:touch_one_layer];


This creates a layer with the circle and makes that a sublayer of the view layer. The reason opacity is 0 is that the circle is usually invisible.

Now in the single touch event handler of the view controller, I have:


- (void)handleOneFingerTap:(UITapGestureRecognizer *)gestureRecognizer
{
CALayer *touch_one_layer = self.v.touch_one_layer;

[CATransaction begin];
[CATransaction setDisableActions:TRUE];
touch_one_layer.position=[gestureRecognizer locationInView:v];
[CATransaction commit];

[touch_one_layer addAnimation:touch_animation forKey:@"animateOpacity"];

touch_one_layer.opacity=0;
}


This makes the circle pop up, and then gradually fades out. "v" in the code is my custom view.

Now the final routine, the missing link, touch_animation. touch_animation is an instance of CABasicAnimation, defined as:



touch_animation=[CABasicAnimation animationWithKeyPath:@"opacity"];
touch_animation.duration=1.0;
touch_animation.repeatCount=0;
touch_animation.fromValue=[NSNumber numberWithFloat:1.0];
touch_animation.toValue=[NSNumber numberWithFloat:0.0];
touch_animation.removedOnCompletion=FALSE;
[touch_animation retain];



BTW, simply setting the opacity of the layer does not work reliably. I tried.