ios CABasicAnimation - 变换比例保持在中心
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16447236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CABasicAnimation - transform scale keep in center
提问by Leon Storey
Trying to animatie an ellipse masked on a UIView to be scale transformed remaining in the center position.
试图在 UIView 上对蒙版的椭圆进行动画处理,以保留在中心位置进行缩放。
I have found CALayer - CABasicAnimation not scaling around center/anchorPoint, and followed by adding a bounds
property to the maskLayer
CAShapeLayer
however, this ends with the mask being positioned in the left corner with only 1/4 of it showing. I would like the mask to remain within the center of the screen.
我发现CALayer - CABasicAnimation 没有围绕 center/anchorPoint 缩放,然后添加一个bounds
属性到maskLayer
CAShapeLayer
然而,这以蒙版位于左角结束,只显示了它的 1/4。我希望面具保持在屏幕的中心。
@synthesize maskedView;
- (void)viewDidLoad
{
[super viewDidLoad];
UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Next"];
vc.view.frame = CGRectMake(0,0, self.view.frame.size.width, self.view.frame.size.height);
vc.view.layer.bounds = self.view.layer.bounds;
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = CGRectMake((self.view.frame.size.width/2)-50, (self.view.frame.size.height/2)-50, 100, 100);
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, nil, maskRect);
[maskLayer setPath:path];
CGPathRelease(path);
vc.view.layer.mask = maskLayer;
[self.view addSubview:vc.view];
maskedView = vc.view;
[self startAnimation];
}
Animation...
动画片...
-(void)startAnimation
{
maskedView.layer.mask.bounds = CGRectMake((self.view.frame.size.width/2)-50, (self.view.frame.size.height/2)-50, 100, 100);
maskedView.layer.mask.anchorPoint = CGPointMake(.5,.5);
maskedView.layer.mask.contentsGravity = @"center";
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.duration = 1.0f;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:5.0f];
[maskedView.layer.mask addAnimation:animation forKey:@"animateMask"];
}
Update
更新
I seem to have fixed this with a second animation on the position
key. Is this correct or is there a better way of doing this?
我似乎已经用position
键上的第二个动画修复了这个问题。这是正确的还是有更好的方法来做到这一点?
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"position"];
animation2.duration = 1.0f;
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation2.fromValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))];
animation2.toValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))];
[toBeMask.layer.mask addAnimation:animation2 forKey:@"animateMask2"];
采纳答案by Leon Storey
I seem to have fixed this with a second animation on the position key. Is this correct or is there a better way of doing this?
我似乎已经用位置键上的第二个动画修复了这个问题。这是正确的还是有更好的方法来做到这一点?
CABasicAnimation *animation2 = [CABasicAnimation animationWithKeyPath:@"position"];
animation2.duration = 1.0f;
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
animation2.fromValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))];
animation2.toValue = [NSValue valueWithCGPoint:CGPointMake((self.view.frame.size.width/2), (self.view.frame.size.height/2))];
[toBeMask.layer.mask addAnimation:animation2 forKey:@"animateMask2"];
回答by nevyn
You can create a scale around the center of the object instead of (0, 0) like this:
您可以创建围绕对象中心而不是 (0, 0) 的比例,如下所示:
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform"];
CATransform3D tr = CATransform3DIdentity;
tr = CATransform3DTranslate(tr, self.bounds.size.width/2, self.bounds.size.height/2, 0);
tr = CATransform3DScale(tr, 3, 3, 1);
tr = CATransform3DTranslate(tr, -self.bounds.size.width/2, -self.bounds.size.height/2, 0);
scale.toValue = [NSValue valueWithCATransform3D:tr];
So we start out with the "identity" transform (which means 'no transform'). Then we translate (move) to the center of the object. Then we scale. Then we move back to origo so we're back where we started (we only wanted to affect the scale operation).
所以我们从“身份”变换开始(这意味着“无变换”)。然后我们平移(移动)到对象的中心。然后我们进行缩放。然后我们回到原点,回到我们开始的地方(我们只想影响缩放操作)。
回答by facumenzella
I am not sure why, but CAShapeLayer does not set the bounds property to the layer. In my case, that's was the problem. Try setting the bounds. That should work.
我不知道为什么,但 CAShapeLayer 没有为图层设置 bounds 属性。就我而言,这就是问题所在。尝试设置界限。那应该工作。
I did something like this for building the initial circle
我做了这样的事情来建立初始圈
self.circle = [CAShapeLayer layer];
CGRect roundedRect = CGRectMake(0, 0, width, width);
self.circle.bounds = roundedRect;
UIBezierPath *start = [UIBezierPath bezierPathWithRoundedRect:roundedRect cornerRadius:width/2];
[self.circle setPath:start.CGPath];
self.circle.position = CGPointMake(whatever suits you);
self.circleView.layer.mask = self.circle;
[self.circleView.layer.mask setValue: @(1) forKeyPath: @"transform.scale"];
And something like this for scaling it
像这样的东西来缩放它
CABasicAnimation *scale = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
scale.fromValue = [self.circleView.layer.mask valueForKeyPath:@"transform.scale"];
scale.toValue = @(100);
scale.duration = 1.0;
scale.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.circleView.layer.mask setValue:scale.toValue forKeyPath:scale.keyPath];
[self.circleView.layer.mask addAnimation:scale forKey:scale.keyPath];
PD: AnchorPoint is by default (.5,.5) according to apple documentations...but we all know that does not mean anything right?
PD:根据苹果文档,AnchorPoint 默认为 (.5,.5) ......但我们都知道这并不意味着什么,对吗?
Hope it helps!!
希望能帮助到你!!
回答by Aamir
I have written following function with many added tweaks and options, could be useful for many others.
我编写了以下功能,并添加了许多调整和选项,可能对其他人有用。
func layerScaleAnimation(layer: CALayer, duration: CFTimeInterval, fromValue: CGFloat, toValue: CGFloat) {
let timing = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
let scaleAnimation: CABasicAnimation = CABasicAnimation(keyPath: "transform.scale")
CATransaction.begin()
CATransaction.setAnimationTimingFunction(timing)
scaleAnimation.duration = duration
scaleAnimation.fromValue = fromValue
scaleAnimation.toValue = toValue
layer.add(scaleAnimation, forKey: "scale")
CATransaction.commit()
}
Note:Don't forget to update size after animation completion, because CATransaction reverts back to actual size.
注意:不要忘记在动画完成后更新大小,因为 CATransaction 会恢复到实际大小。