How to adjust drop shadow dynamically during an UI

2019-03-19 16:26发布

问题:

I use the following to code to add drop shadow:

letterE.layer.shadowColor = [[UIColor blackColor] CGColor];
letterE.layer.shadowOffset = CGSizeMake(2.5, 2.5);
letterE.layer.shadowRadius = 3.0;
letterE.layer.shadowOpacity = 0.95;

and the following to rotate:

CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0];
rotationAnimation.duration = 5.0;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = 1.0; 
rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

[letterE.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

During the animation, the shadow is static which looks weird:

How can I make the shadow dynamically updated during the animation?

回答1:

I found this interesting so I gave it a shot. A possible solution is to build a second clear view under the main view, giving it (the bottom view) a shadow using the original view's path. Then you can apply the animation to both views. I did this with simple rectangular views but I see no reason why this can't be done with more complex paths or using 2 CALayers instead of 2 UIViews.

This is how I set up my views...

testView = [[UIView alloc] initWithFrame:CGRectMake(40, 40, 100, 100)];
testView.backgroundColor = [UIColor redColor];

//increase y origin of second view to simulate shadow offset
testViewShadow = [[UIView alloc] initWithFrame:CGRectMake(40, 50, 100, 100)];

CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0, 0, testView.frame.size.width, testView.frame.size.height)); 
testViewShadow.layer.shadowPath = path;
testViewShadow.layer.shadowOpacity = 1.0;
testViewShadow.layer.shadowOffset = CGSizeMake(0, 0);
testViewShadow.layer.shadowRadius = 10.0;
CFRelease(path);

[self.view addSubview:testViewShadow];
[self.view addSubview:testView];

..and my animation (just hooked up your CAAnimation to a button as an IBAction and applied to both views)...

- (IBAction)rotate:(id)sender{
    CABasicAnimation* rotationAnimation;
    rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0];
    rotationAnimation.duration = 5.0;
    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = 1.0; 
    rotationAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    [testView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
    [testViewShadow.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

This is what the result looks like...

Any (2D) transformations should look believable if you apply them to both views.

Hope that helps!