【问题标题】:Smooth writing on iPad在 iPad 上流畅书写
【发布时间】:2011-09-19 08:30:10
【问题描述】:

我目前正在处理一个 iPad 项目,我需要让用户使用触控笔在一张纸上书写的功能。

我测试了几支手写笔,发现竹子是最好的。他们还有一个免费的应用程序,您可以使用它来编写。

我面临的问题是我使用的方法不能提供平滑的曲线。竹纸应用程序提供完美的线条。这是我到目前为止的代码:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    UIGraphicsBeginImageContext(self.frame.size);

    // draw accumulated lines
    if ([self.lines count] > 0) {
        for (Line *tempLine in self.lines){
            CGContextSetAlpha(context, tempLine.opacity);
            CGContextSetStrokeColorWithColor(context, tempLine.lineColor.CGColor);
            CGContextSetLineWidth(context, tempLine.lineWidth);
            CGContextSetLineCap(context, kCGLineCapRound);
            CGContextSetLineJoin(context, kCGLineJoinRound);
            CGContextAddPath(context, tempLine.linePath);
            CGContextStrokePath(context);

            }
    }

    //draw current line
    CGContextSetAlpha(context, self.currentLine.opacity);


    CGContextSetStrokeColorWithColor(context, self.currentLine.lineColor.CGColor);
    CGContextSetLineWidth(context, self.currentLine.lineWidth);
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextSetLineJoin(context, kCGLineJoinRound);
    CGContextBeginPath(context);
    CGContextAddPath(context, self.currentLine.linePath);
    CGContextStrokePath(context);


    UIGraphicsEndImageContext();


}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];
    CGPoint cPoint = [touch locationInView:self];

    CGPathMoveToPoint(self.currentLine.linePath, NULL, cPoint.x, cPoint.y);

    [self setNeedsDisplay];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *touch = [touches anyObject];   
    CGPoint currentPoint = [touch locationInView:self];

    CGPathAddLineToPoint(self.currentLine.linePath, NULL, currentPoint.x, currentPoint.y);

    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {  
    UITouch *touch = [touches anyObject];
    CGPoint cPoint = [touch locationInView:self];
    CGPathAddLineToPoint(self.currentLine.linePath, NULL, cPoint.x, cPoint.y);

    [self setNeedsDisplay];
    [self.lines addObject:self.currentLine];
    Line *nextLine = [[Line alloc] initWithOptions:self.currentLine.lineWidth color:self.currentLine.lineColor opacity:self.currentLine.opacity];
    self.currentLine = nextLine;
    [nextLine release];
}

这些图片清楚地说明了我面临的问题。这是使用上面提供的代码编写时生成的图像:

如果我在 Mamboo 纸质应用程序上写同样的东西,这就是图像:

有没有人知道如何在 mamboo 应用程序中获得漂亮的文字?

【问题讨论】:

标签: iphone ios xcode ipad opengl-es


【解决方案1】:

您应该尝试使用贝塞尔曲线,而不是使用直线 (CGPathAddLineToPoint) 连接点:CGPathAddCurveToPointCGPathAddQuadCurveToPoint

这就是平滑的作用。


如果您不熟悉贝塞尔曲线,您可能会发现the wikipedia page about Bézier curves 很有趣(不是特别是数学方程式,而是看草图和动画图像)。它将让您大致了解控制点如何影响线条关键点周围线条的平滑度。

对于您的情况,二次曲线(两个关键点之间的每个子段只有一个控制点)就足够了。

(从 P0 到 P1 的一条线,使用控制点 P1 平滑)


计算每个关键点 A 和 B 之间的控制点 C 的一个示例(开箱即用,只是我脑海中的一个建议,从未测试过,根据您的需要调整系数)是使 AC 成为,例如,AB 长度的 2/3,和 (AB,AC) 形成 30 度或类似的角度。

您甚至可以在应用的设置中建议使用滑块调整平滑强度,这将影响您选择的值来计算每个控制点并查看最适合的系数。 p>

【讨论】:

  • 好吧,我从来没有在 iOS 应用程序中使用过贝塞尔曲线(如果我没记错的话,我确实在几年前将它们用于 java 游戏)我会在互联网上搜索一些好的例子。如果您有一些很好的例子,请告诉我:D 感谢您的回答! (我现在使用的 linePath 对象是 CGMutablePathRef)
  • 不确定你是否看过,但我在第一次回复后编辑了我的答案并提出了一些建议;)
  • 我不明白的是如何在触摸事件处理程序中使用它。因为我总是有 x 和 y 值,如果我认为它正确,该方法要求至少 4 分...
  • CGPathAddQuadCurveToPoint,按照建议用来绘制二次曲线,只需要两个点:目标点(x,y),和CGPathAddLineToPoint完全一样,加上一个控制点(cx, cy) 将控制平滑。您应该按照我的回答和绘图方法(而不是触摸事件)中的建议计算此控制点(这是您与CGPathAddLineToPoint 案例相比的唯一额外点)
  • 请注意,这样,当您在屏幕上移动手指时,您在触摸事件处理程序中执行的绘图仍将绘制直线,但当您松开手指并构建 Line 对象时将它添加到您的self.lines 然后询问setNeedsDisplay,这就是您在drawRect 方法中的迭代,它将计算控制点(对于self.lines 中的线)并平滑绘图。所以即使在画的时候你会一直画直线直到你松开手指,一旦你画完并触发touchesEnded,整体绘图就会变得平滑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-02-07
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-05
相关资源
最近更新 更多