4

我在 UIView 对象中使用 Quartz 2D 来绘制多条曲线,如下例所示:

使用 Quartz 2D 和 <code>CGContextStrokePath</code> 绘制的两条曲线

这是我现在的代码(我省略了控制点和其他东西的计算):

for (int i = 1; i < points.count; ++i) {
  CGContextMoveToPoint(context, previousXValue, previousYValue);
  CGContextAddCurveToPoint(context,
    firstControlPointXValue, firstControlPointYValue,
    secondControlPointXValue, secondControlPointYValue,
    xValue, yValue
  );

  // CGContextFillPath(context);
  CGContextStrokePath(context);
}

现在我想填充曲线下方的区域,但如果我使用CGContextFillPath结果如下:

使用 Quartz 2D 和 <code>CGContextFillPath</code> 填充两条曲线

这是有道理的,因为根据Quartz 2D 文档

当您填充当前路径时,Quartz 就像路径中包含的每个子路径都已关闭一样。然后它使用这些封闭的子路径并计算要填充的像素。

然后我尝试将路径移动到右下角并关闭路径,但是填充方法没有任何效果:

CGContextMoveToPoint(context, rect.size.width, rect.size.height);
CGContextClosePath(context);
CGContextFillPath(context);

如何填充曲线下方的整个区域,而不仅仅是每个子路径中封闭的子区域?

编辑:

我找到了一个临时解决方案:在每个子路径上使用曲线和两条垂直线绘制形状:

for (int i = 1; i < points.count; ++i) {
  // Draw the curve
  CGContextMoveToPoint(context, previousXValue, previousYValue);
  CGContextAddCurveToPoint(context,
    firstControlPointXValue, firstControlPointYValue,
    secondControlPointXValue, secondControlPointYValue,
    xValue, yValue
  );
  CGContextStrokePath(context);

  // Draw a shape using curve's initial and final points
  CGContextMoveToPoint(context, previousXValue, rect.size.height);
  CGContextAddLineToPoint(context, previousXValue, previousYValue);
  CGContextAddCurveToPoint(context,
    firstControlPointXValue, firstControlPointYValue,
    secondControlPointXValue, secondControlPointYValue,
    xValue, yValue
  );
  CGContextAddLineToPoint(context, xValue, rect.size.height);
  CGContextFillPath(context);
}

我不知道这是否矫枉过正,因此也欢迎改进。此外,我得到了这个结果:

使用 Quartz 2D 绘制的两条曲线,并填充了它们下方的区域

请注意,垂直线是由于绘制相邻的子区域而出现的。怎么能避免呢?

4

1 回答 1

3

这个想法是正确的,但您不应该填充单个曲线,而是创建一条路径然后填充它。所以,从CGContextMoveToPoint左下角开始,CGContextAddLineToPoint到你的第一个点,CGContextAddCurveToPoint对所有的曲线做一个,最后,CGContextAddLineToPoint对右下角做一个(你也可以做一个CGContextClosePath好的测量)。

这是一个简化的示例,其中我只有一个点数组,但它说明了这个想法:

- (void)drawRect:(CGRect)rect
{
    if (!self.points)
        [self configurePoints];

    DataPoint *point;

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGColorRef color = [[UIColor redColor] CGColor];
    CGContextSetStrokeColorWithColor(context, color);
    CGContextSetFillColorWithColor(context, color);

    point = self.points[0];

    CGContextMoveToPoint(context, point.x, self.bounds.size.height);
    CGContextAddLineToPoint(context, point.x, point.y);

    for (point in self.points)
    {
        // you'd do your CGContextAddCurveToPoint here; I'm just adding lines
        CGContextAddLineToPoint(context, point.x, point.y);
    }

    point = [self.points lastObject];
    CGContextAddLineToPoint(context, point.x, self.bounds.size.height);
    CGContextClosePath(context);

    CGContextDrawPath(context, kCGPathFillStroke);
}
于 2013-04-23T16:47:06.727 回答