set dar、scale、rotate preference,由外部控制动画,onRecord可测试#76
set dar、scale、rotate preference,由外部控制动画,onRecord可测试#76CloudlessMoon wants to merge 8 commits intodebugly:mainfrom
Conversation
|
为了修复macOS上手动旋转时画面显示感觉闪烁的bug,故意做了这个动画来避免。为了不突兀改成所有手动调节的设置项都有动画。 你这么改回去的话那macOS上这个bug怎么搞?实际上也只有iOS上才会有你之前优化的那个问题,因为mac不支持旋转屏幕。 |
macOS上也由业务实现动画即可: 若按照之前
macOS也有问题,旋转屏幕只是其中的一种场景,实际上当以 |
|
动画放在外部的话,意味着:“我们知道有bug,需要使用者自己去解决”。使用者如果不知道设定个动画,那么就会出现主动设置旋转时画面闪烁问题,这种情况我不想看到,因为属于功能回退了。反倒是现在打的补丁能解决这个问题,并且违和下用户主动这个场景,给个动画是可以接受的。 “实际上当以动画的形式去设置FSMetalView的frame都会有之前的拉伸变形问题”,是的,现在的动画在设定旋转时是拉伸的,但设置dar和scalingMode没问题。 我没有更好的办法了,我试了编写动画组模拟 iOS 系统旋转屏的效果做旋转,但是那样会导致和播放器底层渲染的旋转叠加,比如设定旋转90度,实际旋转180的奇怪效果,试着顺着这个路子往下解决需要处理的事情更加复杂了。 // 1. 确保开启 Layer 支持
self.renderedView.wantsLayer = YES;
CALayer *realLayer = self.renderedView.layer;
// 2. 记录当前状态作为动画起点
// macOS 下使用 presentationLayer 获取当前视觉上的真实位置
CATransform3D startTransform = realLayer.presentationLayer.transform;
CGPoint startPosition = realLayer.presentationLayer.position;
CGRect startBounds = realLayer.presentationLayer.bounds;
// 3. 计算目标值
CGFloat rotateRadian = (zDegrees / 180.0) * M_PI;
CGRect targetBounds = CGRectMake(0, 0, size.width, size.height);
CGPoint targetPosition = CGPointMake(origin.x + size.width / 2.0, origin.y + size.height / 2.0);
CATransform3D targetTransform = CATransform3DMakeRotation(rotateRadian, 0, 0, 1);
// 4. 【关键】同步 Model 层并禁用隐式动画
[CATransaction begin];
[CATransaction setDisableActions:YES];
realLayer.anchorPoint = CGPointMake(0.5, 0.5);
realLayer.position = targetPosition;
realLayer.bounds = targetBounds;
realLayer.transform = targetTransform;
[CATransaction commit];
// 5. 创建显式动画
// 使用 transform 属性整体动画,比单独动 rotation.z 更稳定
CABasicAnimation *transformAnim = [CABasicAnimation animationWithKeyPath:@"transform"];
transformAnim.fromValue = [NSValue valueWithCATransform3D:startTransform];
transformAnim.toValue = [NSValue valueWithCATransform3D:targetTransform];
CABasicAnimation *positionAnim = [CABasicAnimation animationWithKeyPath:@"position"];
positionAnim.fromValue = [NSValue valueWithPoint:startPosition]; // macOS 使用 valueWithPoint
positionAnim.toValue = [NSValue valueWithPoint:targetPosition];
CABasicAnimation *boundsAnim = [CABasicAnimation animationWithKeyPath:@"bounds"];
boundsAnim.fromValue = [NSValue valueWithRect:startBounds]; // macOS 使用 valueWithRect
boundsAnim.toValue = [NSValue valueWithRect:targetBounds];
// 6. 组合动画
CAAnimationGroup *animGroup = [CAAnimationGroup animation];
animGroup.animations = @[transformAnim, positionAnim, boundsAnim];
animGroup.duration = 0.35;
animGroup.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// 既然 Model 层已经改了,这里千万不要用 FillModeForwards
animGroup.removedOnCompletion = YES;
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// 动画结束后的业务逻辑
self.animating = NO;
self.renderedView.frame = CGRectMake(origin.x, origin.y, size.width, size.height);
[self setNeedsRefreshCurrentPic];
}];
[realLayer addAnimation:animGroup forKey:@"rotateFrameAnim"];
[CATransaction commit]; |
现在的补丁也没有解决问题,就算了加了动画也还有闪烁的问题,只是没有之前明显了,反而是增加了几个副作用。 分析下这个“闪烁”问题产生的原因,分为优化前和优化后,优化前是指没有使用frame,完全使用Metal来控制scalingMode等参数,优化后是指使用frame来控制scalingMode等参数。 以下描述的「横竖屏」旋转特指业务中改变FSMetalView的frame,「横竖屏」只是其中的一种场景,能够直观的体现这一行为。
① 优化前:「横竖屏」时会出现拉伸和闪烁的问题;非「横竖屏」则不会出现 可以看到优化后「不管是否在横竖屏」中都解决了scalingMode、darPreference拉伸和闪烁问题,但rotatePreference没有解决,结合上面的讨论,可以分析得出: 但rotatePreference就不一样了, 解决rotatePreference拉伸和闪烁问题,只有一个办法,就是通过设置renderedView的transform或者transform3D来实现rotatePreference,去掉 macOS上则是通过rotateByAngle等属性实现。 |
* 'main' of https://github.com/debugly/fsplayer: demo test http proxy 更新 apple.yml generate FSPlayer.xcodeproj in source root dir
|
既然问题出自这个frame的设定,那么何不在即将旋转时去修改frame,修正你提出的画面变形问题,在旋转结束后再把frame修改回来,解决设置旋转角度问题,这样是不是就能完美解决了? |
问题原因是设置frame必须在主线程,set rotatePreference是metal线程,就算在主线程调用draw也不行,因为总有一帧对应新的frame。 实际上这些属性要么都用frame去实现,要么都用metal去draw,结合使用就会有上述问题。 目前开源的播放器例如https://github.com/libobjc/SGPlayer https://github.com/kingslay/KSPlayer ,或多或少都有我在上面提过的问题,闭源的例如阿里云播放器解决的比较粗暴,直接将CATransaction关闭了,也就是说视图层没办法实现动画了,腾讯云播放器处理的比较好,腾讯是完全用metalLayer去draw,但是它解决了横竖屏旋转画面会被拉伸变形的问题 |
|
我尝试过关闭 CATransaction,我也尝试了我说的旋转结束后再把frame修改回来,改回来的时候发现只要改frame就会出现画面闪下,感觉又回到了我加动画缓解变形的现场了。 我又找到了一个新思路,改动简单,你可以看下有啥问题没。我看效果挺好的,画面没有拉伸变形,围绕中心点旋转。 |
|
只是改了内容显示模式,不会影响 Core Animation 的工作啊。 |
设置内容显示模式不会影响,但是之前通过设置frame会自动应用Core Animation,也就是说横竖屏旋转场景会有个默认的动画,可以看看#66 这个PR中的视频,与现在的有些差别。 |
|
是的,设置frame会触发隐式动画。现在有一点瑕疵,但比最初好太多了。 |



678b498#commitcomment-175793545