如何同步多个CALayer的绘制 解决拖拽绘制对象时的坐标错位问题
解决方案
优先优化(可完全解决错位问题)
如果拖拽过程中绘制对象本身的内容没有发生变化,仅坐标改变,不要对两个图层调用setNeedsDisplay,直接修改两个图层的position/frame属性即可。CALayer的位置变更默认走硬件加速渲染,无需触发重绘,天然不会出现绘制不同步问题,同时拖拽性能会大幅提升。
若拖拽时必须重绘内容,可采用以下方案降低错位概率
方案1:用显式
CATransaction包裹所有更新操作,强制两个图层的绘制请求在同一个渲染周期提交[CATransaction begin]; // 禁用隐式动画避免额外延迟 [CATransaction setDisableActions:YES]; // 先统一更新两个图层依赖的所有状态,确保两者拿到的是同一份坐标数据 targetLayer.position = newPosition; hoverLayer.position = newPosition; // 再统一触发重绘 [targetLayer setNeedsDisplay]; [hoverLayer setNeedsDisplay]; [CATransaction commit];方案2:悬浮层对齐绘制层的
presentationLayer
高开销绘制层重绘时,模型层坐标已经更新但屏幕实际显示的是presentationLayer的状态,可通过CADisplayLink绑定屏幕刷新周期,每次刷新时同步悬浮层坐标到绘制层的当前显示位置:// 初始化时添加刷新回调 self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(syncHoverLayer)]; [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - (void)syncHoverLayer { CALayer *presentLayer = self.targetLayer.presentationLayer ?: self.targetLayer; self.hoverLayer.position = presentLayer.position; // 如果需要同步重绘,也在此处统一触发 [self.hoverLayer setNeedsDisplay]; }方案3:差异化配置异步绘制开关
给高开销的绘制层开启异步绘制,低开销的悬浮层关闭异步绘制,让悬浮层的绘制在主线程立刻完成,等待绘制层的异步渲染结果后统一提交,大幅减少两者的完成时间差:// 高开销绘制层配置 targetLayer.drawsAsynchronously = YES; // 悬浮层配置 hoverLayer.drawsAsynchronously = NO;方案4:简化悬浮层实现消除重绘开销
如果悬浮层仅做高亮效果,优先用CALayer自带属性(borderWidth/borderColor/shadowOpacity等)实现,或提前把高亮效果生成静态图片赋值给hoverLayer.contents,完全避免悬浮层调用setNeedsDisplay,从根源上消除悬浮层的绘制延迟。
内容的提问来源于stack exchange,提问作者user3494959
相关产品推荐
相关产品推荐

