Antialiasing edges of UIView after transformation using CALayer's transform

后端 未结 4 936
别跟我提以往
别跟我提以往 2020-12-12 22:44

I have a UIView object that rotates using CALayer\'s transform:

// Create uiview object.
UIImageView *block = [[UIImageView alloc]          


        
相关标签:
4条回答
  • 2020-12-12 23:13

    check allowsEdgeAntialiasing property of CALayer.

    block.layer.allowsEdgeAntialiasing = YES; // iOS7 and above.
    
    0 讨论(0)
  • 2020-12-12 23:17

    I had a similar issue when rotating around the z-axis. Setting shouldRasterize = YES prevented the jagged edges however it came at a performance cost. In my case I was re-using the views (and its layers) and keeping the shouldRasterize = YES was slowing things down.

    The solution was, to turn off rasterization right after I didn't need it anymore. However since animation runs on another thread, there was no way of knowing when the animation was complete...until I found out about an extremely useful CATransaction method. This is an actual code that I used and it should illustrate its use:

    // Create a key frame animation
    CAKeyframeAnimation *wiggle = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    NSInteger frequency = 5; // Higher value for faster vibration
    NSInteger amplitude = 25; // Higher value for lower amplitude
    // Create the values it will pass through    
    NSMutableArray *valuesArray = [[NSMutableArray alloc] init];
    NSInteger direction = 1;
    
    [valuesArray addObject:@0.0];
    
    for (NSInteger i = frequency; i > 0; i--, direction *= -1) {
        [valuesArray addObject:@((direction * M_PI_4 * (CGFloat)i / (CGFloat)amplitude))];
    }
    
    [valuesArray addObject:@0.0];
    [wiggle setValues:valuesArray];
    
    // Set the duration
    [wiggle setAdditive:YES];
    [wiggle setValueFunction:[CAValueFunction functionWithName:kCAValueFunctionRotateZ]];
    [wiggle setDuration:0.6];
    
    // Turn on rasterization to prevent jagged edges (anti-aliasing issues)
    viewToRotate.layer.shouldRasterize = YES;
    
    // ************ Important step **************
    // Very usefull method. Block returns after ALL animations have completed.
    [CATransaction setCompletionBlock:^{
        viewToRotate.layer.shouldRasterize = NO;
    }];
    // Animate the layer
    [viewToRotate.layer addAnimation:wiggle forKey:@"wiggleAnimation"];
    

    worked like a charm for me.

    I have not tried using this with implicit animations (i.e. animations that happen due to value change in animatable property for a non-view associated layer), however I would expect it to work as long as the CATransaction method is called before the property change, just as a guarantee the block is given to CATransaction before an animation starts.

    0 讨论(0)
  • 2020-12-12 23:19

    Simply add this key-value pair to your Info.plist: UIViewEdgeAntialiasing set to YES.

    0 讨论(0)
  • 2020-12-12 23:38

    One way to do this is by placing the image inside another view that's 5 pixels bigger. The bigger view should have a transparent rasterized border that will smooth the edges of the UIImageView:

    view.layer.borderWidth = 3; 
    view.layer.borderColor = [UIColor clearColor].CGColor; 
    view.layer.shouldRasterize = YES; 
    view.layer.rasterizationScale = [[UIScreen mainScreen] scale];
    

    Then, place your UIImageView inside this parent view and center it (With 2.5 pixels around each edge).

    Finally, rotate the parent view instead of the image view.

    It works very well - you can also encapsulate the whole thing in class that creates the hierarchy.

    0 讨论(0)
提交回复
热议问题