Pragmatic way of handling mouse in Core Animation layers
I'm starting working with Core Animation and I started wondering how to handle various kinds of mouse events like
- mouse entered a
CALayer
- mous开发者_运维技巧e exited a
CALayer
- mouse click on a
CALayer
For now I'm concentrating just on mouseDown
message sent to my custom view. According to the documentation I should use -hitTest:(CGPoint)point
calling on my root layer (the one set with [customView setLayer:rootLayer]
).
It should return the farthest layer in the tree that is in position specified by point. So I did:
[rootLayer hitTest:[event locationInWindow]]
but it doens't work. It seems to work if I just click on rootLayer
, otherwise it returns just null
. Of course sublayers are added to rootLayer (infact they are drawn)
Am I missing some kind of coordinate conversion? Apart from that, is it the way to handle mouse clicks?
To find whenever mouse enters a CALayer do I have to keep hit testing for every movement update of the mouse?
Thanks in advance
You might want to look at how we handle mouse / touch events in CALayers within the Core Plot framework. We've set up a rudimentary responder chain with our various CALayer subclasses in the layer hierarchy. Recently we added code to scroll a graph using mouse / touch events as an example of how to use this kind of interaction.
I've used something similar myself, only with the mouse click handling being taken care of within the main layer-hosting view. In that view, I overrode -mouseDown: and added code similar to the following:
CGPoint pointOfClick = NSPointToCGPoint([self convertPoint:[theEvent locationInWindow] fromView:nil]);
CALayer *hitLayer = [self.layer hitTest:pointOfClick];
if ( (hitLayer != nil) && [hitLayer isKindOfClass:[MyCustomLayer class]])
{
[(MyCustomLayer *)hitLayer mouseDown];
}
The MyCustomLayer class would be a custom CALayer subclass which responds to the mouseDown method and does some mouse click handling of its own. Alternatively, you could handle the mouse click response entirely within this method of your layer-hosting view.
One thing to make sure of is that if you've subclassed CALayer, its -containsPoint: method still returns YES if the passed point lies within the bounds of your layer. Otherwise, -hitTest: will ignore that layer.
You need to convert locationInWindow
into the containing view's coordinate system. So, if your view is called customView
, you would do this:
[rootLayer hitTest:[customView convertPoint:[event locationInWindow] fromView:nil]];
CALayer
s don't get their own event notifications, so the only way to handle events is by handling them in the containing view.
精彩评论