iphone - 在 View 之间划线的最佳方法是什么?

标签 iphone cocoa-touch core-animation core-graphics calayer

背景:我有一个自定义 ScrollView (子类),其上有可拖动的 uiimageviews,基于我需要在 uiscrollview 的 subview 中动态绘制一些线条的拖动。 (请注意,我需要将它们放在 subview 中,因为稍后我需要更改 View 的不透明度。)

因此,在我花费大量时间开发代码之前(我是新手,所以这需要我一段时间),我研究了我需要做什么并找到了一些可能的方法。只是想知道执行此操作的正确方法是什么。

  1. 创建 UIView 的子类并使用 drawRect 方法绘制我需要的线条(但不确定如何使其动态读取值)
  2. 在 subview 上使用 CALayers 并在那里绘图
  3. 使用 CGContext 函数创建画线方法
  4. 还有别的事吗?

为帮助干杯

最佳答案

从概念上讲,您的所有主张都是相似的。所有这些都会导致以下步骤(其中一些是由 UIKit 无形地完成的):

  1. 在内存中设置位图上下文。
  2. 使用 Core Graphics 将线条绘制到位图中。
  3. 将此位图复制到 GPU 缓冲区(纹理)。
  4. 使用 GPU 构建图层( View )层次结构。

上述步骤中最昂贵的部分是前三点。它们会导致重复的内存分配、内存复制和 CPU/GPU 通信。另一方面,你真正想做的是轻量级的:画一条线,可能动画开始/结束点,宽度,颜色,alpha,...

有一个简单的方法可以做到这一点,完全避免所描述的开销:为您的线条使用 CALayer,但不用在 CPU 上重新绘制内容,只需用线条的颜色完全填充它(设置其 backgroundColor 属性设置为线条的颜色。然后修改图层的位置、边界、变换属性,使 CALayer 准确覆盖线条的区域。

当然,这种方法只能画直线。但也可以通过将 contents 属性设置为图像来修改它以绘制复杂的视觉效果。例如,使用这种技术,您可以在线上获得发光效果的模糊边缘。

虽然这种技术有其局限性,但我在 iPhone 和 Mac 上的不同应用程序中经常使用它。它始终比基于核心图形的绘图具有显着优越的性能。

编辑:计算图层属性的代码:

void setLayerToLineFromAToB(CALayer *layer, CGPoint a, CGPoint b, CGFloat lineWidth)
{
    CGPoint center = { 0.5 * (a.x + b.x), 0.5 * (a.y + b.y) };
    CGFloat length = sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
    CGFloat angle = atan2(a.y - b.y, a.x - b.x);

    layer.position = center;
    layer.bounds = (CGRect) { {0, 0}, { length + lineWidth, lineWidth } };
    layer.transform = CATransform3DMakeRotation(angle, 0, 0, 1);
}

第二次编辑: Here's a simple test project这显示了 Core Graphics 和基于 Core Animation 的渲染在性能上的巨大差异。

第三次编辑:结果非常令人印象深刻:渲染 30 个可拖动 View ,每个 View 彼此连接(产生 435 条线),使用 Core Animation 在 iPad 2 上以 60Hz 流畅渲染。使用经典方法时,帧速率降至 5 Hz,并且最终会出现内存警告。

Performance comparison Core Graphics vs. Core Animation

关于iphone - 在 View 之间划线的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5847876/

相关文章:

iPhone - UIView 添加 subview 与drawRect?

objective-c - 如何将自定义单元格添加到 UITableView 的底部?

ios - collectionView分为三行swift 4

iphone - 如何跳过警报 "You' 已购买此但尚未下载”

objective-c - iOS 6 中用于完成 block 的 dispatch_get_current_queue() 的替代方案?

iphone - NSURLConnection 和处理响应代码和响应数据

ios - 无法使用 ARKit (ARKit + CoreLocation) 对场景节点进行动画处理

ios - 从 CABasicAnimation 转换代码

iphone - 如何慢慢抚摸露出路径?

iphone - 在 "centre"模式下,如何在 UIImageView 中缩放图像? (换帧不起作用)