我正在尝试沿着路径移动平面,因为用户正在定义它,类似于飞行控制中的控件。我能够绘制路径,虽然效率低下,但我不能让飞机顺利地沿着路径动画。
我最初尝试使用通过更改位置提供的隐式动画沿路径移动平面,但由于它不允许我改变动画的速度,因此平面表现不佳。
我现在尝试递归地使用动画块,但是很快就会调用完成块,导致平面跟随正在绘制的路径。
这是设置代码:
- (CALayer *)plane{
if(!_plane){
_plane = [CALayer layer];
UIImage *planeImage = [UIImage imageNamed:@"airplane.png"];
_plane.bounds = CGRectMake(20.0, 20.0, planeImage.size.width, planeImage.size.height);
_plane.contents = (id)(planeImage.CGImage);
[self.layer addSublayer:_plane];
}
return _plane;
}
- (void)touchesEnded:(NSSet *)touches
withEvent:(UIEvent *)event{
if(isDrawingPath){
[self.trackPath addLineToPoint:[[touches anyObject] locationInView:self]];
NSLog(@"%@", self.trackPath);
UITouch *touch = [touches anyObject];
CGPoint toPoint = [touch locationInView:self];
//now, save each point in order to make the path
[self.points addObject:[NSValue valueWithCGPoint:toPoint]];
[self setNeedsDisplay];
[self goToPointWithIndex:0];
}
isDrawingPath = NO;
}
这种实施方式有效,但很糟糕。飞机沿着这条路走,但它很不稳定:
- (void)goToPointWithIndex:(NSNumber *)indexer{
int toIndex = [indexer intValue];
if(toIndex < self.points.count){
//extract the value from array
CGPoint toPoint = [(NSValue *)[self.points objectAtIndex:toIndex] CGPointValue];
CGPoint pos = self.plane.position;
float delay = PLANE_SPEED * (sqrt( pow(toPoint.x - pos.x, 2) + pow(toPoint.y - pos.y, 2)));
self.plane.position = toPoint;
// Allows animation to continue running
if(toIndex < self.points.count - 1){
toIndex++;
}
//float delay = 0.2;
NSLog(@"%f", delay);
//repeat the method with a new index
//this method will stop repeating as soon as this "if" gets FALSE
NSLog(@"index: %d, x: %f, y: %f", toIndex, toPoint.x, toPoint.y);
[self performSelector:@selector(goToPointWithIndex:) withObject:[NSNumber numberWithInt:toIndex] afterDelay:delay];
}
}
这就是我想用块做的事情。它只是跳到绘制路径的末尾而不是跟随整个事物。
- (void)goToPointWithIndex:(int)toIndex{
if(self.resetPath) return;
//extract the value from array
if(toIndex < self.points.count) {
CGPoint toPoint = [(NSValue *)[self.points objectAtIndex:toIndex] CGPointValue];
NSLog(@"index: %d, x: %f, y: %f", toIndex, toPoint.x, toPoint.y);
CGPoint pos = self.plane.position;
//float delay = PLANE_SPEED * (sqrt( pow(toPoint.x - pos.x, 2) + pow(toPoint.y - pos.y, 2)));
// Allows animation to continue running
if(toIndex < self.points.count - 1){
toIndex++;
}
[UIView animateWithDuration:0.2
animations:^{
self.plane.position = toPoint;
}
completion:^(BOOL finished) {
if(finished == YES) {NSLog(@"Complete");[self goToPointWithIndex:toIndex];}
}];
}
}
我不知道我哪里出错了。我是Objective-c和block的新手。完成块是否应该在动画开始后立即运行?这对我来说没有意义,但它是我能找到的唯一解释。
答案 0 :(得分:1)
由于此处self.plane
是自定义CALayer
(与支持UIView
的图层相对),因此不会尊重UIView animateWithDuration:
的参数
来自docs:
自定义图层对象忽略基于视图的动画块参数,而是使用默认的Core Animation参数。
而是使用CABasicAnimation
和CALayer's
addAnimation:forKey:
方法(在这种情况下可能是CAAnimationGroup
)。 "Animating Layer Content."
CALayers
制作动画
答案 1 :(得分:0)
某些原因你只是覆盖了touchesEnded?然后,您只会为屏幕上的任何手指路径选取一个点。在我看来,你应该覆盖touchesMoved并且也可以触摸开始(并且或多或少地与touchesEnded一样)。