我被我认为是一个简单的问题所困扰。
我想绘制由线连接的视图,动画视图的位置,并使连接线也有动画。我创建视图,并在它们之间创建如下一行:
- (UIBezierPath *)pathFrom:(CGPoint)pointA to:(CGPoint)pointB {
CGFloat halfY = pointA.y + 0.5*(pointB.y - pointA.y);
UIBezierPath *linePath=[UIBezierPath bezierPath];
[linePath moveToPoint: pointA];
[linePath addLineToPoint:CGPointMake(pointA.x, halfY)];
[linePath addLineToPoint:CGPointMake(pointB.x, halfY)];
[linePath addLineToPoint:pointB];
return linePath;
}
-(void)makeTheLine {
CGPoint pointA = self.viewA.center;
CGPoint pointB = self.viewB.center;
CAShapeLayer *lineShape = [CAShapeLayer layer];
UIBezierPath *linePath=[self pathFrom:pointA to:pointB];
lineShape.path=linePath.CGPath;
lineShape.fillColor = nil;
lineShape.opacity = 1.0;
lineShape.strokeColor = [UIColor blackColor].CGColor;
[self.view.layer addSublayer:lineShape];
self.lineShape = lineShape;
}
它画出了我想要的样子。我从文档中了解到,我可以在动画块中修改形状的路径,如下所示:
- (void)moveViewATo:(CGPoint)dest {
UIBezierPath *destPath=[self pathFrom:dest to:self.viewB.center];
[UIView animateWithDuration:1 animations:^{
self.viewA.center = dest;
self.lineShape.path = destPath.CGPath;
}];
}
但没有骰子。视图位置按预期进行动画,但是连接到另一个视图的线会立即跳转到目标路径。
This answer意味着我所做的应该是有效的。this answer建议使用CABasic动画,这在我看来更糟,因为(a)然后我需要与对视图所做的更酷的块动画进行协调,(b)当我尝试这种方式时,线条一点也没有改变.
// worse way
- (void)moveViewATo:(CGPoint)dest {
UIBezierPath *linePath=[self pathFrom:dest to:self.viewB.center];
[UIView animateWithDuration:1 animations:^{
self.viewA.center = dest;
//self.lineShape.path = linePath.CGPath;
}];
CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"];
morph.duration = 1;
morph.toValue = (id)linePath.CGPath;
[self.view.layer addAnimation:morph forKey:nil];
}
提前谢谢。
发布于 2015-05-20 08:10:50
谢谢大家的帮助。在我问这个问题之后,我发现我是在绘制错误的属性。结果,您可以在动画中替换图层的形状,如下所示:
CABasicAnimation *morph = [CABasicAnimation animationWithKeyPath:@"path"];
morph.duration = 1;
morph.fromValue = (__bridge id)oldPath.path;
morph.toValue = (__bridge id)newPath.CGPath;
[line addAnimation:morph forKey:@"change line path"];
line.path=linePath.CGPath;
发布于 2015-04-30 13:44:16
我想这就是你所需要的
#import "ViewController.h"
@interface ViewController ()
//the view to animate, nothing but a simple empty UIView here.
@property (nonatomic, strong) IBOutlet UIView *targetView;
@property (nonatomic, strong) CAShapeLayer *shapeLayer;
@property NSTimeInterval animationDuration;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//the shape layer appearance
self.shapeLayer = [[CAShapeLayer alloc]init];
self.shapeLayer.strokeColor = [UIColor blackColor].CGColor;
self.shapeLayer.fillColor = [UIColor clearColor].CGColor;
self.shapeLayer.opacity = 1.0;
self.shapeLayer.lineWidth = 2.0;
[self.view.layer insertSublayer:self.shapeLayer below:self.targetView.layer];
//animation config
self.animationDuration = 2;
}
- (UIBezierPath *)pathFrom:(CGPoint)pointA to:(CGPoint)pointB {
CGFloat halfY = pointA.y + 0.5*(pointB.y - pointA.y);
UIBezierPath *linePath=[UIBezierPath bezierPath];
[linePath moveToPoint: pointA];
[linePath addLineToPoint:CGPointMake(pointA.x, halfY)];
[linePath addLineToPoint:CGPointMake(pointB.x, halfY)];
[linePath addLineToPoint:pointB];
return linePath;
}
- (void) moveViewTo: (CGPoint) point {
UIBezierPath *linePath= [self pathFrom:self.targetView.center to:point];
self.shapeLayer.path = linePath.CGPath;
//Use CAKeyframeAnimation to animate the view along the path
//animate the position of targetView.layer instead of the center of targetView
CAKeyframeAnimation *viewMovingAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
viewMovingAnimation.duration = self.animationDuration;
viewMovingAnimation.path = linePath.CGPath;
//set the calculationMode to kCAAnimationPaced to make the movement in a constant speed
viewMovingAnimation.calculationMode =kCAAnimationPaced;
[self.targetView.layer addAnimation:viewMovingAnimation forKey:viewMovingAnimation.keyPath];
//draw the path, animate the keyPath "strokeEnd"
CABasicAnimation *lineDrawingAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
lineDrawingAnimation.duration = self.animationDuration;
lineDrawingAnimation.fromValue = [NSNumber numberWithDouble: 0];
lineDrawingAnimation.toValue = [NSNumber numberWithDouble: 1];
[self.shapeLayer addAnimation:lineDrawingAnimation forKey:lineDrawingAnimation.keyPath];
//This part is crucial, update the values, otherwise it will back to its original state
self.shapeLayer.strokeEnd = 1.0;
self.targetView.center = point;
}
//the IBAction for a UITapGestureRecognizer
- (IBAction) viewDidTapped:(id)sender {
//move the view to the tapped location
[self moveViewTo:[sender locationInView: self.view]];
}
@end
一些解释:
UIViewAnimation
,当动画完成时,属性值将被更改。对于CALayerAnimation
,属性值永远不会改变,它只是一个动画,当动画完成后,该层将进入其原始状态(在本例中为路径)。self.lineShape.path = linePath.CGPath
不起作用是因为self.linePath
是CALayer
而不是UIView
,所以必须使用CALayerAnimation
来动画CALayer
strokeEnd
而不是path
动画路径绘图。我不知道path
为什么在最初的帖子里工作,但我觉得很奇怪。CAKeyframeAnimation
(而不是CABasicAnimation
或UIViewAnimation
)用于在路径上动画视图。(我想你更喜欢这个,而不是直接从起点到终点的线性动画)。将calculationMode
设置为kCAAnimationPaced
将使动画具有恒定的速度,否则视图的移动将与绘制的直线不同步。https://stackoverflow.com/questions/29976687
复制相似问题