我正在尝试使用setBeginTime将图层的不透明度和位置动画延迟3秒。我已经调用了图层boxLayer。然而,动画在前3秒(该图层不应显示)中运行良好,图层将显示在其最终位置和不透明度。它不应该。组动画无法解决问题。有人可以帮忙吗?请参阅以下代码:
// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// Maintain opacity to 1.0 JUST TO MAKE SURE IT DOES NOT GO BACK TO ORIGINAL OPACITY
[boxLayer setOpacity:endOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// Maintain the end position at 400.0 450.0 OTHERWISE IT IS GOING BACK TO ORIGINAL POSITION
[boxLayer setPosition:CGPointMake(endX, endY)];
答案 0 :(得分:17)
问题是,您要将boxLayer
和position
的{{1}}属性设置为其最终值。你需要:
将opacity
属性设置为它们的起始值,而不是它们的结束值(这就是为什么它从结束位置/不透明度开始...通常如果动画立即开始,这不是问题,但因为你推迟了开始,使用结束位置是有问题的);
对于您的两个动画,您必须将boxLayer
更改为removedOnCompletion
,将NO
更改为fillMode
(这是阻止其恢复原状的正确方法完成后到原来的位置。
因此:
kCAFillModeForwards
就我个人而言,我认为你在视图上使用基于块的动画更容易完成的工作做了很多工作(为了演示的目的,我假设你的// Create an animation that will change the opacity of a layer
CABasicAnimation *fader = [CABasicAnimation animationWithKeyPath:@"opacity"];
// It will last 1 second and will be delayed by 3 seconds
[fader setDuration:1.0];
[fader setBeginTime:CACurrentMediaTime()+3.0];
// The layer's opacity will start at 0.0 (completely transparent)
[fader setFromValue:[NSNumber numberWithFloat:startOpacity]];
// And the layer will end at 1.0 (completely opaque)
[fader setToValue:[NSNumber numberWithFloat:endOpacity]];
// MAKE SURE IT DOESN'T CHANGE OPACITY BACK TO STARTING VALUE
[fader setRemovedOnCompletion:NO];
[fader setFillMode:kCAFillModeForwards];
// Add it to the layer
[boxLayer addAnimation:fader forKey:@"BigFade"];
// SET THE OPACITY TO THE STARTING VALUE
[boxLayer setOpacity:startOpacity];
// Create an animation that will change the position of a layer
CABasicAnimation *mover = [CABasicAnimation animationWithKeyPath:@"position"];
// It will last 1 second and will be delayed by 3 seconds
[mover setDuration:1.0];
[mover setBeginTime:CACurrentMediaTime()+3.0];
// Setting starting position
[mover setFromValue:[NSValue valueWithCGPoint:CGPointMake(startX, startY)]];
// Setting ending position
[mover setToValue:[NSValue valueWithCGPoint:CGPointMake(endX, endY)]];
// MAKE SURE IT DOESN'T MOVE BACK TO STARTING POSITION
[mover setRemovedOnCompletion:NO];
[mover setFillMode:kCAFillModeForwards];
// Add it to the layer
[boxLayer addAnimation:mover forKey:@"BigMove"];
// SET THE POSITION TO THE STARTING POSITION
[boxLayer setPosition:CGPointMake(startX, startY)];
是一个对于名为boxLayer
的控件,CALayer
。如果你这样做,你也不需要Quartz 2D:
box
答案 1 :(得分:1)
要使用fillMode
,您应该对动画对象进行必要的配置,并将kCAFillModeBackwards
设置为zoomAnimation.fillMode = kCAFillModeBackwards;
,如
var MongoClient = require('mongodb').MongoClient,
test = require('assert');
MongoClient.connect('mongodb://localhost:27017/test', function(err, db) {
// Get a collection
var shoes = db.collection('shoes');
shoes.update({
"attr": {
"$elemMatch": {
"k": "manufacturer",
"v": "ShoesForAll"
}
},
"attr.k": "style"
}, {
$set: {
"attr.$.v": "sport"
},
},
{
multi: true
},
function(err, numAffected) {
shoes.update({
"attr": {
"$elemMatch": {
"k": "manufacturer",
"v": "ShoesForAll"
}
},
"attr.k": "color"
}, {
$set: {
"attr.$.v": "red"
}
},
{
multi: true
},
function(err, numAffected) {
db.close();
}
)
}
)
})
在Apple文档中说:
使用beginTime属性设置动画的开始时间。通常,动画在下一个更新周期开始。您可以使用beginTime参数将动画开始时间延迟几秒钟。将两个动画链接在一起的方法是将一个动画的开始时间设置为与另一个动画的结束时间相匹配。 如果延迟动画的开始,您可能还需要将fillMode属性设置为kCAFillModeBackwards。即使图层树中的图层对象包含不同的值,此填充模式也会使图层显示动画的起始值。如果没有此填充模式,您将看到在动画开始执行之前跳转到最终值。其他填充模式也可用。
另外,来自Rob的问题:
对于您的两个动画,您必须将removedOnCompletion更改为NO并将fillMode更改为kCAFillModeForwards(这是使其在完成时不会恢复到原始位置的正确方法)。
这是一种有争议的陈述,因为:
移除动画后,表示层将回退到模型图层的值,由于我们从未修改过该图层的位置,因此我们的太空飞船会重新出现在它开始的位置。 有两种方法可以解决这个问题:
第一种方法是直接在模型层上更新属性。这是推荐的方法,因为它使动画完全可选。
或者,您可以通过将其fillMode属性设置为kCAFillModeForwards来告诉动画保持其最终状态,并通过将removedOnCompletion设置为NO来防止动画自动删除。但是,保持模型和表示层同步是一个很好的做法,所以应该谨慎使用这种方法。
答案 2 :(得分:0)
本文解释了为什么不应将removedOnCompletion与fillMode https://www.objc.io/issues/12-animations/animations-explained/一起使用
在我的情况下,我正在设置一个视图层,该视图用作导航,但延迟了该视图内的反弹动画;我需要在层上更新这些位置,因为它可以被解雇然后再次显示。一旦动画完成,使用removedOnCompletion将不会更新图层的值
我这样做是在CATransaction完成块中更新图层
CATransaction.setCompletionBlock {
// update the layer value
}
CATransaction.begin()
// setup and add your animation
CATransaction.commit()