gpt4 book ai didi

ios - 使用 CABasicAnimation(CAAnimation) 自定义交互过渡

转载 作者:行者123 更新时间:2023-12-01 18:50:25 24 4
gpt4 key购买 nike

我想用 UIViewAnimation 构建交互式过渡。但是我可以为它设置动画的图层属性很少。所以我决定使用 CAAnimation。
我想更改 ViewController 的 View 掩码,这是代码

-(NSTimeInterval)transitionDuration:(nullable id<UIViewControllerContextTransitioning>)transitionContext{
return 0.5f;
}


-(void)animateTransition:(nonnull id<UIViewControllerContextTransitioning>)transitionContext{

_transitionContext=transitionContext;
UIViewController *fromVC=
[transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toVC=
[transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIView *containerView=[transitionContext containerView];

_toVC=toVC;
_fromVC=fromVC;
[containerView insertSubview:toVC.view aboveSubview:fromVC.view];

//Create the BezierPath
UIBezierPath *initailPath=[UIBezierPath bezierPathWithRect:(CGRect) {{_cellRect.size.width/2,_cellRect.origin.y+_cellRect.size.height/2},.size= {0.5,0.5}}];
CGFloat radius;
CGFloat distance;
if (fromVC.view.frame.size.width>fromVC.view.frame.size.height) {
distance=fromVC.view.frame.size.width-_cellRect.origin.x;
radius=distance>_cellRect.origin.x?distance:_cellRect.origin.x+88;
}else{
distance=fromVC.view.frame.size.height-_cellRect.origin.y;
radius=distance>_cellRect.origin.y?distance:_cellRect.origin.y+88;
}
radius=radius*2;
UIBezierPath *finalPath=[UIBezierPath bezierPathWithOvalInRect:CGRectInset(_cellRect,
- radius,
- radius)];
_initaialPath=initailPath;
_finalPath=finalPath;
//Create a Layer Mask
_maskLayer=[[CAShapeLayer alloc] init];
_maskLayer.path=finalPath.CGPath;
toVC.view.layer.mask=_maskLayer;


[self animateLayer:_maskLayer withCompletion:^{

BOOL isComple=![transitionContext transitionWasCancelled];
if (!isComple) {

[containerView addSubview:fromVC.view];
[toVC.view removeFromSuperview];
}
[transitionContext completeTransition:isComple];
}];
}
-(void)startInteractiveTransition:(nonnull id<UIViewControllerContextTransitioning>)transitionContext{

_transitionContext=transitionContext;
[self animateTransition:transitionContext];
[self pauseTime:[_transitionContext containerView].layer];

}

这是主要动画,无需交互即可完美运行。
然后我尝试用这些代码控制它:
-(void)updateInteractiveTransition:(CGFloat)percentComplete{
[_transitionContext updateInteractiveTransition:percentComplete];
[_transitionContext containerView].layer.timeOffset=_pausedTime + [self transitionDuration:_transitionContext]*percentComplete;
}

-(void)finishInteractiveTransition{

[_transitionContext finishInteractiveTransition];
[self resumeTime:[_transitionContext containerView].layer];
}

这两个功能完美运行

但是 这是“取消转换”的问题
当我取消过渡时,它突然消失
(我已尝试使用此 question 中的解决方案,但这对我不起作用)
这是我的代码:
- (void)cancelInteractiveTransition {
//Must Cancel System InteractiveTransition FRIST
[_transitionContext cancelInteractiveTransition];
//Then adjust the layer time
CALayer *maskLayer =[_transitionContext containerView].layer;
maskLayer.beginTime = CACurrentMediaTime();
//MOST IMPORTANT
[UIView animateWithDuration:0.5 animations:^{

maskLayer.timeOffset=0.0;

} completion:^(BOOL finished) {

[[_transitionContext containerView ] addSubview:_fromVC.view];
[_toVC.view removeFromSuperview];
}];

}

现在我几乎花了整整一个星期的时间,如果你能帮助我,我真的断言。

最佳答案

我们可以轻松地将图层的属性从初始值设置为最终值。
一般当我们想要实现一个交互动画的时候,我们可以使用 UIView 的动画 block 来达到这个(Go to final position 或者 back to original position)。但是您不能使用诸如 BackgroundColour、CGPath 之类的属性来执行此操作。

实际上我们可以通过使用CAAnimation来控制这个过程,并且控制
CALayer 的时间偏移量。当我们在某个精确位置控制动画过程时。我们怎样才能让它回到动画过程?如果你控制的属性是位置。

    [UIView animateWithDuration:/*Left time*/ 
delay:/*delay time*/
usingSpringWithDamping:/*damping*/
initialSpringVelocity:/*speed*/
options:/*option*/
animations:^{

/*Your animation*/

} completion:^(BOOL finished) {

}];

但它不适合 CGPath 或 BackgroundColor 之类的东西。

我们需要一种方法来驱动动画,苹果已经支持一个驱动程序,这个驱动程序会调用一个你指定的函数。它会像 iPhone 屏幕一样每秒执行 60 次。
技术是 CADisplayLink 目的。它是一个计时器对象,允许您的应用程序将您的绘图与显示器的刷新率同步。

然后我得到了解决方案:
if (!_displayLink) {
_displayLink=[CADisplayLink displayLinkWithTarget:self selector:@selector(animationTick:)];
[_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

AnimationTick Function 是您要刷新的函数:
-(void)animationTick:(CADisplayLink *)displayLink{

CALayer *maskLayer=[_transitionContext containerView].layer;
CGFloat timeOffset=maskLayer.timeOffset;
timeOffset=MAX(0,timeOffset-_piceDistance);
maskLayer.timeOffset=timeOffset;
if (timeOffset==0) {
displayLink.paused=YES;
}
}

就这样

关于ios - 使用 CABasicAnimation(CAAnimation) 自定义交互过渡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31403370/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com