CAAnimation 为复选标记绘图设置动画
CAAnimation to animate a checkmark drawing
我正在尝试制作一个简单的复选标记控件,其中仅包含一个正方形和一个复选标记。我想在点击控件时为复选标记的绘制和擦除设置动画。这是我目前所拥有的:
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: checkBox.size * 2 / 3))
path.addLine(to: CGPoint(x: checkBox.size / 3, y: checkBox.size))
path.addLine(to: CGPoint(x: checkBox.size, y: 0))
pathLayer.frame = checkBox.bounds
pathLayer.path = path.cgPath
pathLayer.strokeColor = UIColor.red().cgColor
pathLayer.fillColor = nil
pathLayer.lineWidth = checkMarkWidth
pathLayer.lineJoin = kCALineJoinBevel
let pathAnimation = CABasicAnimation(keyPath:"strokeEnd")
pathAnimation.duration = checkMarkAnimationDuration
pathAnimation.fromValue = NSNumber(floatLiteral: 0)
pathAnimation.toValue = NSNumber(floatLiteral: 1)
let reverseAnimation = CABasicAnimation(keyPath:"strokeEnd")
reverseAnimation.duration = checkMarkAnimationDuration
reverseAnimation.fromValue = NSNumber(floatLiteral: 1)
reverseAnimation.toValue = NSNumber(floatLiteral: 0)
reverseAnimation.delegate = self
然后我开始这样的动画:
var on: Bool = false {
didSet {
if on {
checkBox.layer.addSublayer(pathLayer)
pathLayer.removeAllAnimations()
pathLayer.add(pathAnimation, forKey:"strokeEnd")
} else {
pathLayer.removeAllAnimations()
pathLayer.add(reverseAnimation, forKey:"strokeEnd")
}
}
}
最后在我的 CAAnimationDelegate 中我这样做了:
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
pathLayer.removeFromSuperlayer()
}
这看起来不错,除了当我在真实设备上测试它时,当反转动画完成时,但在图层被移除之前,有一点闪光。看来我缺少一个 animationWillStop
回调。
有什么办法解决这个问题吗?
也欢迎任何其他关于如何改进此代码的建议,因为我是 Core Animation 的新手。
Core Animation 有三层树,一层是 模型层树,您最常与之交互。一个是 表示层树 ,其中包含飞行中的 运行 动画值。最后一个是 render layer tree,它实际上是渲染层并且是 Core Animation 私有的。
CAAnimation 只改变 CALayer 的 presentationLayer 的值。动画结束后,动画被移除,strokeEnd 跳回 到你的模态层的值:1.0。这就是为什么你有闪光灯。
所以,你可以改变
var on: Bool = false {
didSet {
if on {
checkBox.layer.addSublayer(pathLayer)
pathLayer.removeAllAnimations()
pathLayer.add(pathAnimation, forKey:"strokeEnd")
} else {
pathLayer.removeAllAnimations()
pathLayer.add(reverseAnimation, forKey:"strokeEnd")
}
}
}
到
var on: Bool = false {
didSet {
if on {
checkBox.layer.addSublayer(pathLayer)
pathLayer.strokeEnd = 1.0 // set property to final state
pathLayer.removeAllAnimations()
pathLayer.add(pathAnimation, forKey:"strokeEnd")
} else {
pathLayer.strokeEnd = 0.0 // set property to final state
pathLayer.removeAllAnimations()
pathLayer.add(reverseAnimation, forKey:"strokeEnd")
}
}
}
您可以执行以下步骤:
第一步:
- 创建一个名为 CheckMarkAnimation 的 xcode 项目。
在您的界面构建器中添加一个带有图像“checkmark.png”的 UIImageView。
第二步:
- 我刚刚编写了下面的代码片段。
#import
#define RectWidth(f) f.size.width
#define RectHeight(f) f.size.height
- (void)doMaskAnimationOnCheckMarck:(UIImageView*)imgView duration:(NSTimeInterval)duration delay:(NSTimeInterval)delay alpha:(CGFloat)alpha{
UIBezierPath * fromPath = [UIBezierPath bezierPathWithRect:CGRectMake(0,0, 1,RectHeight(imgView.bounds))];
UIBezierPath * toPath = [UIBezierPath bezierPathWithRect:imgView.bounds];
CAShapeLayer * maaskLayer = [CAShapeLayer layer];
maaskLayer.path = toPath.CGPath;
maaskLayer.fillColor = [UIColor colorWithWhite:1.0 alpha:alpha].CGColor;
imgView.layer.mask = maskLayer;
CABasicAnimation * animation = [CABasicAnimation animation]; animation.keyPath = @"path";
animation.beginTime = CACurrentMediaTime() + delay;
animation.fromValue = (__bridge id)fromPath.CGPath; animation.toValue = (__bridge id)toPath.CGPath;
animation.duration = duration;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[maaskLayer addAnimation:animation forKey:@"MaskAnimation"];
}
你使用这个 link 应该会有更好的运气,如下所示。
How to animate a checkmark Using Bezier path as Clipping Mask in iOS
希望对您有所帮助。
我正在尝试制作一个简单的复选标记控件,其中仅包含一个正方形和一个复选标记。我想在点击控件时为复选标记的绘制和擦除设置动画。这是我目前所拥有的:
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y: checkBox.size * 2 / 3))
path.addLine(to: CGPoint(x: checkBox.size / 3, y: checkBox.size))
path.addLine(to: CGPoint(x: checkBox.size, y: 0))
pathLayer.frame = checkBox.bounds
pathLayer.path = path.cgPath
pathLayer.strokeColor = UIColor.red().cgColor
pathLayer.fillColor = nil
pathLayer.lineWidth = checkMarkWidth
pathLayer.lineJoin = kCALineJoinBevel
let pathAnimation = CABasicAnimation(keyPath:"strokeEnd")
pathAnimation.duration = checkMarkAnimationDuration
pathAnimation.fromValue = NSNumber(floatLiteral: 0)
pathAnimation.toValue = NSNumber(floatLiteral: 1)
let reverseAnimation = CABasicAnimation(keyPath:"strokeEnd")
reverseAnimation.duration = checkMarkAnimationDuration
reverseAnimation.fromValue = NSNumber(floatLiteral: 1)
reverseAnimation.toValue = NSNumber(floatLiteral: 0)
reverseAnimation.delegate = self
然后我开始这样的动画:
var on: Bool = false {
didSet {
if on {
checkBox.layer.addSublayer(pathLayer)
pathLayer.removeAllAnimations()
pathLayer.add(pathAnimation, forKey:"strokeEnd")
} else {
pathLayer.removeAllAnimations()
pathLayer.add(reverseAnimation, forKey:"strokeEnd")
}
}
}
最后在我的 CAAnimationDelegate 中我这样做了:
public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
pathLayer.removeFromSuperlayer()
}
这看起来不错,除了当我在真实设备上测试它时,当反转动画完成时,但在图层被移除之前,有一点闪光。看来我缺少一个 animationWillStop
回调。
有什么办法解决这个问题吗?
也欢迎任何其他关于如何改进此代码的建议,因为我是 Core Animation 的新手。
Core Animation 有三层树,一层是 模型层树,您最常与之交互。一个是 表示层树 ,其中包含飞行中的 运行 动画值。最后一个是 render layer tree,它实际上是渲染层并且是 Core Animation 私有的。
CAAnimation 只改变 CALayer 的 presentationLayer 的值。动画结束后,动画被移除,strokeEnd 跳回 到你的模态层的值:1.0。这就是为什么你有闪光灯。
所以,你可以改变
var on: Bool = false {
didSet {
if on {
checkBox.layer.addSublayer(pathLayer)
pathLayer.removeAllAnimations()
pathLayer.add(pathAnimation, forKey:"strokeEnd")
} else {
pathLayer.removeAllAnimations()
pathLayer.add(reverseAnimation, forKey:"strokeEnd")
}
}
}
到
var on: Bool = false {
didSet {
if on {
checkBox.layer.addSublayer(pathLayer)
pathLayer.strokeEnd = 1.0 // set property to final state
pathLayer.removeAllAnimations()
pathLayer.add(pathAnimation, forKey:"strokeEnd")
} else {
pathLayer.strokeEnd = 0.0 // set property to final state
pathLayer.removeAllAnimations()
pathLayer.add(reverseAnimation, forKey:"strokeEnd")
}
}
}
您可以执行以下步骤:
第一步:
- 创建一个名为 CheckMarkAnimation 的 xcode 项目。 在您的界面构建器中添加一个带有图像“checkmark.png”的 UIImageView。
第二步:
- 我刚刚编写了下面的代码片段。
#import
#define RectWidth(f) f.size.width
#define RectHeight(f) f.size.height
- (void)doMaskAnimationOnCheckMarck:(UIImageView*)imgView duration:(NSTimeInterval)duration delay:(NSTimeInterval)delay alpha:(CGFloat)alpha{
UIBezierPath * fromPath = [UIBezierPath bezierPathWithRect:CGRectMake(0,0, 1,RectHeight(imgView.bounds))];
UIBezierPath * toPath = [UIBezierPath bezierPathWithRect:imgView.bounds];
CAShapeLayer * maaskLayer = [CAShapeLayer layer];
maaskLayer.path = toPath.CGPath;
maaskLayer.fillColor = [UIColor colorWithWhite:1.0 alpha:alpha].CGColor;
imgView.layer.mask = maskLayer;
CABasicAnimation * animation = [CABasicAnimation animation]; animation.keyPath = @"path";
animation.beginTime = CACurrentMediaTime() + delay;
animation.fromValue = (__bridge id)fromPath.CGPath; animation.toValue = (__bridge id)toPath.CGPath;
animation.duration = duration;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[maaskLayer addAnimation:animation forKey:@"MaskAnimation"];
}
你使用这个 link 应该会有更好的运气,如下所示。
How to animate a checkmark Using Bezier path as Clipping Mask in iOS
希望对您有所帮助。