iOS版动画面膜过的UIImage [英] iOS Animate Mask Over UIImage

查看:275
本文介绍了iOS版动画面膜过的UIImage的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用的雨燕1.2和我的目标是在一个静态的UIImage动画图像遮罩。我所实行的是掩盖了我本来在Objective-C中的图像的迅速版本。

I am using Swift 1.2 and my goal is to animate an image mask over a static UIImage. What I have implemented is a swift version of masking an image that I originally found in Objective-C.

func maskImage(image: UIImage, mask: UIImage) -> UIImage! {

    let maskRef = mask.CGImage;

    let mask = CGImageMaskCreate(
        CGImageGetWidth(maskRef),
        CGImageGetHeight(maskRef),
        CGImageGetBitsPerComponent(maskRef),
        CGImageGetBitsPerPixel(maskRef),
        CGImageGetBytesPerRow(maskRef),
        CGImageGetDataProvider(maskRef), nil, false);

    let masked = CGImageCreateWithMask(image.CGImage, mask);
    let retImage = UIImage(CGImage: masked);
    return retImage;
}

它的伟大工程!然而,把它在运动中是我的挑战。

It works great! However, putting it in motion is my challenge.

有要么反复用不同的水平偏移或更好的方式来完全解决这个问题,敷面膜的方式 - 也许一个CALayer的执行

Is there a way to either iteratively apply the mask with a different horizontal offset or a better way to approach this problem entirely - perhaps with a CALayer implementation?

感谢您的帮助!

编辑:基于什么被张贴作为一个答案,我加了这一点:

Based on what was posted as an answer, I added this:

    let image = UIImage(named: "clouds");

    let imageView = UIImageView(image: image);
    let layer = CALayer();
    layer.contents = UIImage(named: "alpha-mask")?.CGImage;
    layer.bounds = CGRectMake(0, 0, image.size.width, image.size.height);

    // For other folks learning, this did not work
    //let animation = CABasicAnimation(keyPath: "bounds.origin.x");

    // This does work
    let animation = CABasicAnimation(keyPath: "position.x");

    animation.duration = 2;
    animation.delegate = self;
    animation.fillMode = kCAFillModeForwards;
    animation.repeatCount = 0;
    animation.fromValue = 0.0;
    animation.toValue = image.size.width;
    animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear);
    animation.removedOnCompletion = false;

    layer.addAnimation(animation, forKey: "transform");

    imageView.layer.mask = layer;

    self.addSubview(imageView);

我能看到正确的alpha面具,但动画不起作用。任何想法?

I am able to see the alpha mask properly, but the animation does not work. Any ideas?

编辑:我修改了code以上和它的作品!我需要做的keyPath position.x。见上文

I modified the code above and it works! I needed to make the keyPath position.x. See above

推荐答案

您确实希望使用CALayer的 - 或者更确切地说,一个CAShapeLayer

You do indeed want to use a CALayer - or rather, a CAShapeLayer.

您可以创建一个CAShapeLayer并安装它作为作为另一层面具。

You can create a CAShapeLayer and install it as as the mask on another layer.

您可以创建一个动画改变形状图层的路径CAAnimation,也可以设置动画更改图层的strokeStart和/或strokeEnd属性。

You can create a CAAnimation that animates changes to the shape layer's path, or you can animate changes to the layer's strokeStart and/or strokeEnd properties.

如果您动画路径,要遵循一个规则是确保起点和终点的路径具有相同数量和控制点的类型。否则,动画不确定,其结果可能是非常奇怪的。

If you animate the path, the one rule you want to follow is to make sure that the starting and ending path have the same number and type of control points. Otherwise the animation is "undefined", and the results can be very strange.

我有一个发展的博客文章,概述了它是如何完成的:

I have a development blog post that outlines how it's done:

<一个href=\"http://wareto.com/using-core-animation-groups-to-create-animation-sequences-2\">http://wareto.com/using-core-animation-groups-to-create-animation-sequences-2

这主要是关于使用CAAnimationGroups,但它也包括这些会用来作为图像视图的层的掩模动画变为CAShapeLayer一个工作示例

It's primarily about using CAAnimationGroups, but it also includes a working example of animating changes to a CAShapeLayer that's used as the mask of an image view's layer.

下面是它创建的遮罩动画的GIF - 一个时钟擦除,显示并隐藏图像视图:

Below is a GIF of the mask animation that it creates - a "clock wipe" that shows and hides an image view:

不幸的是写在Objective-C,但核心动画调用是斯威夫特几乎相同。让我知道如果你有任何问题搞清楚如何去适应它。

Unfortunately it's written in Objective-C, but the Core Animation calls are nearly identical in Swift. Let me know if you have any problems figuring out how to adapt it.

动画code的肉是这样的方法:

The meat of the animation code is this method:

- (IBAction)doMaskAnimation:(id)sender;
{

  waretoLogoLarge.hidden = FALSE;//Show the image view

  //Create a shape layer that we will use as a mask for the waretoLogoLarge image view
  CAShapeLayer *maskLayer = [CAShapeLayer layer];

  CGFloat maskHeight = waretoLogoLarge.layer.bounds.size.height;
  CGFloat maskWidth = waretoLogoLarge.layer.bounds.size.width;

  CGPoint centerPoint;
  centerPoint = CGPointMake( maskWidth/2, maskHeight/2);

  //Make the radius of our arc large enough to reach into the corners of the image view.
  CGFloat radius = sqrtf(maskWidth * maskWidth + maskHeight * maskHeight)/2;

  //Don't fill the path, but stroke it in black.
  maskLayer.fillColor = [[UIColor clearColor] CGColor];
  maskLayer.strokeColor = [[UIColor blackColor] CGColor];

  maskLayer.lineWidth = radius; //Make the line thick enough to completely fill the circle we're drawing

  CGMutablePathRef arcPath = CGPathCreateMutable();

  //Move to the starting point of the arc so there is no initial line connecting to the arc
  CGPathMoveToPoint(arcPath, nil, centerPoint.x, centerPoint.y-radius/2);

  //Create an arc at 1/2 our circle radius, with a line thickess of the full circle radius
  CGPathAddArc(arcPath,
               nil,
               centerPoint.x,
               centerPoint.y,
               radius/2,
               3*M_PI/2,
               -M_PI/2,
               YES);

  maskLayer.path = arcPath;

  //Start with an empty mask path (draw 0% of the arc)
  maskLayer.strokeEnd = 0.0;

  CFRelease(arcPath);

  //Install the mask layer into out image view's layer.
  waretoLogoLarge.layer.mask = maskLayer;

  //Set our mask layer's frame to the parent layer's bounds.
  waretoLogoLarge.layer.mask.frame = waretoLogoLarge.layer.bounds;

  //Create an animation that increases the stroke length to 1, then reverses it back to zero.
  CABasicAnimation *swipe = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
  swipe.duration = 2;
  swipe.delegate = self;
  [swipe setValue: theBlock forKey: kAnimationCompletionBlock];

  swipe.timingFunction = [CAMediaTimingFunction 
    functionWithName:kCAMediaTimingFunctionLinear];
  swipe.fillMode = kCAFillModeForwards;
  swipe.removedOnCompletion = NO;
  swipe.autoreverses = YES;

  swipe.toValue = [NSNumber numberWithFloat: 1.0];

  [maskLayer addAnimation: swipe forKey: @"strokeEnd"];
}

我还有一个博客条目的斯威夫特演示了如何使用 CAShapeLayer 以创建和动画饼图。该项目动画造型,没有面具,而唯一的区别是你是否安装形状图层作为常规内容层或像图像视图的衬里层另一层面具。

I have another blog entry that IS in Swift that shows how to create and animate a pie chart using a CAShapeLayer. That project animates shape, not a mask, but the only real difference is whether you install the shape layer as a regular content layer or as a mask on another layer like the backing layer of an image view.

您可以在此链接查看该项目:

You can check out that project at this link:

http://wareto.com/swift-piecharts

这篇关于iOS版动画面膜过的UIImage的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆