Search code examples
pathuiscrollviewuiimageviewscalecashapelayer

Help - Scaling CAShapeLayer (i.e. path) in UIScrollView


I have a problem and I hope you can help me with it. This is for iPad by the way.

I have a UIScrollView, UIImageView, CAShapeLayer, and a CGMutablePathRef.

1- So, I loaded an Image in the UIImageView

2- Then, I parsed all the paths from a file, then added them to CAShapeLayer(s) i.e. each CAShapeLayer is a path.

3- Then I added all the CAShapeLayer(s) to the UIImageView.layer

4- I did step 3 so I can use the function below to return the view that holds the image and the paths. This helps scaling the paths and the image together.

- (UIView *)viewForZoomingInScrollView: (UIScrollView *)scrollView 
{
    return myUIImageView;
}

5- Then I added the UIImageView to the UIScrollView.

6- Then I subclassed the UIScrollView so I can get touchesBegan etc..

*Note: All my touch events such as the touchesBegan are able to detect all the paths when I click on them by using CGPathContainsPoint(aLayer.path, &transf, touchPoint, NO). Also, I can scroll in the view after zooming as well and it works fine.

*Now The Problem Is:

  • Whenever I zoom in/out, the CAShapeLayer(s) get scaled fine, but it seems that the (original coordinates of the paths) do not get scaled, or at least that is what I believe. I am saying this because when I click on the CAShapeLayer(s), they do not respond, but when I click on their original place or close to where the CAShapeLayer shown, I get the CAShapeLayer responding.

  • I tried to get all the CAShapeLayer(s) into an array, erase them from the view, and add them again, but the did not change anything. I tried other stuff as well such as trying to scale the CAShapeLayer(s) separately, by adding the CAShapeLayer(s) to the UIScrollView instead of the UIImageView. Then I get the current applied scale and apply it to the all the CAShapeLayer(s), but that did not produce a good result.

-Check the attached screenshots. I hope they help.

I hope you can help me with it, thanks in advance.

*Before Scaling Image: http://imageshack.us/photo/my-images/193/beforescaling.jpg/

*After Scaling Image: http://imageshack.us/photo/my-images/818/afterscaling.jpg/

**Edited:

-Potential solutions:

1- It might be that I need to update the CATransform3DIdentity of the CAShapeLayer. However, I do not know how to do it yet.

2- It could be that I need to use CATransform3DTranslate, but I do not know how to use it yet.


Solution

  • I guess I'll answer it after I finally found out. To those who may get stuck like me, simply do this.

    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    
    {
        for (UITouch *touch in touches) 
    
        {
              // The [self.view.subviews objectAtIndex:0]] is the view that I want to check whether the CAShapedLayer is touched or not.
              CGPoint touchPoint = [self.view convertPoint:[touch locationInView:self.view] toView:[self.view.subviews objectAtIndex:0]];
        }
    
    }
    

    More Details:

    When the the scroll view scales a view, it doesn't change the internal coordinate system of that view, only its external coordinate system. Since hit-testing the CAShapeLayer in the internal coordinate system of the image view, you should convert your touch points to that view's coordinate system before doing the hit testing.