Search code examples
objective-cioscalayeruibezierpathcgpath

How to add shadow to a group of CALayer using CATransform3D


How can I add shadow to a group of CALayers? I have a "FoldingView"-class which maintans several "SliceView"-classes. Each sliceview's layer will be givven a CATransform3D where I'm using the perspective property (.m34 = 1.0 / -1000).

How can I add a shadow with good visual logic? This is what I've been thinking so far:

  1. I could get the path of each slice and combine these to get a shadow path.

    • I don't know how the get a path of CALayer when the layer is using CATransform3D
    • It might work visually, but I'm afraid it won't be totally right if the light is supposed to come from top left.
  2. I could just apply standard CALayer shadow to all layers

    • It does not look good due to the shadow is overlapping each other

If anyone has any other suggestions or know how to code idea number 1 I'll be very happy! Here is a link to the sample project you see screenshot from.

Download zipped application with code

Sample image from application


Solution

  • This seems to work as wanted. This is done per sliceview.

    - (UIBezierPath *)shadowPath
    { 
    
        if(self.progress == 0 && self.position != VGFoldSliceCenter)
        {
            UIBezierPath *path = [UIBezierPath bezierPath];  
            return path;
        }
        else
        { 
            CGPoint topLeft = pointForAnchorPointInRect(CGPointMake(0, 0), self.bounds);
            CGPoint topRight = pointForAnchorPointInRect(CGPointMake(1, 0), self.bounds);
            CGPoint bottomLeft = pointForAnchorPointInRect(CGPointMake(0, 1), self.bounds);
            CGPoint bottomRight = pointForAnchorPointInRect(CGPointMake(1, 1), self.bounds);
    
            CGPoint topLeftTranslated = [self.superview convertPoint:topLeft fromView:self];
            CGPoint topRightTranslated = [self.superview convertPoint:topRight fromView:self];
            CGPoint bottomLeftTranslated = [self.superview convertPoint:bottomLeft fromView:self];
            CGPoint bottomRightTranslated = [self.superview convertPoint:bottomRight fromView:self];
    
            UIBezierPath *path = [UIBezierPath bezierPath];
    
            [path moveToPoint:topLeftTranslated];
            [path addLineToPoint:topRightTranslated];
            [path addLineToPoint:bottomRightTranslated];
            [path addLineToPoint:bottomLeftTranslated];
            [path closePath]; 
    
            return path;
        } 
    }