- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我正在做一个绘图应用程序,我正在尝试平滑我用手指绘制的线条。为此,我正在使用“quadCurveToPoint”函数。但是,我没有做对。
下面是我的代码:
- (void) drawRect:(CGRect)rect
{
[path stroke];
}
- (id) initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
self.multipleTouchEnabled = NO;
path = [UIBezierPath bezierPath];
path.lineWidth = IS_IPAD? 2.0f : 1.0f;
return self;
}
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
m_previousPoint1 = [touch locationInView:self];
m_previousPoint2 = [touch locationInView:self];
m_currentPoint = [touch locationInView:self];
}
//Find the midpoint
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
m_previousPoint2 = m_previousPoint1;
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
[path setFlatness:1.0f];
[path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound];
[path moveToPoint:m_previousPoint1];
[path addLineToPoint:mid1];
[path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint];
[self setNeedsDisplay];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
当我用手指画画时,我得到了如下所示的路径:
我不明白我错过了什么。所以我需要这方面的帮助。
编辑:图片发布 w.r.t.到下面的答案。
谢谢兰 git
最佳答案
您的代码看起来不错。但要解决您提到的问题,请将当前代码更改为以下内容:
改变:
[path moveToPoint:m_previousPoint1];
[path addLineToPoint:mid1];
收件人:
[path moveToPoint:mid1];
[path addLineToPoint:m_previousPoint1];
并改变这个:
[path addQuadCurveToPoint:mid2 controlPoint:m_currentPoint];
收件人:
[path addQuadCurveToPoint:m_currentPoint controlPoint:mid2];
已测试。
附录(WWDC 算法):
背景:
根据 WWDC 的想法是这样的:
1.) 我们不使用当前点,而是使用中点作为起点和终点。
2.) 因此,我们使用实际触摸点作为控制点。
代码分析/修正:
下面是我使用 WWDC 中引入的想法制作的代码的简化版本。
你明白了。几乎。鉴于上述情况,我们需要将 touchesMoved
中的代码更改为以下内容:
1.)
If we are using the mid point as the
ToPoint
value, we need to take care the first case when there is only one current point, because with only one current point, we cannot derive a mid point from it - we need 2 points.
因此,我们需要先“读取”当前点之后的一个点来计算中点。以下是这样做的:
UITouch *touch = [touches anyObject];
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
mid1 = midPoint(m_currentPoint, m_previousPoint1);
if(counter == 1)
{
[path moveToPoint:m_currentPoint];
[path addLineToPoint:mid1];
[self setNeedsDisplay];
}
The variable counter is initially set to 0. So, nothing gets drawn until the second pass when counter is 1. And when it is, we will have 2 points to calculate the mid point.
接下来就是剩下的部分了:
2.)
Once the first case is taken care of, we move forward to the rest of the curve and derive appropriately the points with which we connect the segments:
else if(counter > 1)
{
[path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1];
[self setNeedsDisplay];
}
counter++;
这是紧接在上面第一个 if
之后的 else if
。我们在仅处理第一种情况时进入此处,因为我使用了一个简单的计数器并在每次调用 touchesMoved
时递增它。
这里发生的是我们使用前一个中点作为控制点从前一个中点连接到 mid1
。那么,当前点呢?我们一直在使用它直到下一次通过。
3.) And finally, we take care the last segment of the curve in
touchesEnded
:
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[path addLineToPoint:[[touches anyObject] locationInView:self]];
[self setNeedsDisplay];
}
这只是从您的中点到最后一点画一条线。
最后在touchesBegan
中,我设置counter = 0;
,所以下一条曲线会再次开始上述过程。
我使用模拟器和设备测试了上面的内容,这里是一个屏幕截图:
这是完整的来源:
- (void) touchesBegan:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
counter = 0;
m_previousPoint1 = [touch locationInView:self];
m_currentPoint = [touch locationInView:self];
}
//Find the midpoint
CGPoint midPoint(CGPoint p1, CGPoint p2)
{
return CGPointMake((p1.x + p2.x) * 0.5, (p1.y + p2.y) * 0.5);
}
- (void) touchesMoved:(NSSet *) touches withEvent:(UIEvent *) event
{
UITouch *touch = [touches anyObject];
m_previousPoint1 = m_currentPoint;
m_currentPoint = [touch locationInView:self];
mid1 = midPoint(m_currentPoint, m_previousPoint1);
[path setFlatness:1.0f];
[path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound];
if(counter == 1)
{
[path moveToPoint:m_currentPoint];
[path addLineToPoint:mid1];
[self setNeedsDisplay];
}
else if(counter > 1)
{
[path addQuadCurveToPoint:mid1 controlPoint:m_previousPoint1];
[self setNeedsDisplay];
}
counter++;
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[path addLineToPoint:[[touches anyObject] locationInView:self]];
[self setNeedsDisplay];
}
关于ios - 将 QuadCurve 添加到 UIBezierPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21143614/
我有两个 UIBezierPath,一个表示图像的多边形部分,另一个是要在其上绘制的路径。 我需要找到它们之间的交点,以便只有在这个交点区域内的点才会被着色。 UIBezierPath 中是否有一种方
我正在制作一个应用程序,允许用户用手指在屏幕上绘制不同的颜色。图纸是用 UIBezierPaths 绘制的,但我需要橡皮擦。我确实有一个橡皮擦,它只是一条以背景图像为颜色的路径,但这种方法会导致内存问
我想用 SceneKit 画一条贝塞尔曲线,并认为这会起作用: func drawCurvedLine() { let scene = SCNScene() let scnView =
我在设置为 iPhone (Retina 4-inch) 的模拟器中运行此代码 -(void)drawRect:(CGRect)rect { [[UIColor whiteColor]set]
我想绘制月亮,然后为月亮的阴影设置动画。但启动此代码后,我可以在动画线上看到一些故障: GIF: 为什么会发生这种情况? Playground 代码 here 更新1:此函数创建的两条路径具有不同的角
假设我们有一个 UIBezierPath...它的边界是完全正方形的...像这样: func getExponentPath(rotate180: Bool) -> UIBezierPath {
我想绘制月亮,然后为月亮的阴影设置动画。但启动此代码后,我可以在动画线上看到一些故障: GIF: 为什么会发生这种情况? Playground 代码 here 更新1:此函数创建的两条路径具有不同的角
假设我们有一个 UIBezierPath...它的边界是完全正方形的...像这样: func getExponentPath(rotate180: Bool) -> UIBezierPath {
我正在试验 UIBezierPath。我想做一个 GridView 。 NSInteger yAxisIncremental = 0; NSInteger xAxisIncremental = 0;
我需要使用bezeirPath绘制此形状: 我做了以下事情: 我创建了矩形路径。 然后我添加了五个圈子。 如下面的代码所示: let stickLayerBezeirPath = UIBezierPa
我将 Apple 文档阅读到 UIBezierPath目的。我是否正确理解它不支持相对路径? 我正在尝试将此 svg 路径转换为 UIBezierPath: // svg path m90 36c
我正在尝试制作一个球从用户画线反弹的游戏。绘制线的代码包含在下面并且可以正常工作,但是一旦球与它接触或玩家画一条新线,我将如何删除线? path = [UIBezierPath bezierPath]
我想画一条这样的路径: 这就是我写的: CGFloat radius = 50; UIBezierPath *path = [UIBezierPath bezierPath]; [path moveT
我在 View 中有一个 UIBezierPath 。我想在单击形状时显示警报,但实际发生的情况是,不仅在我单击形状时显示警报,而且当我单击 View 中的任意位置时也会显示警报。 如何更改此代码,以
我正在尝试从圆形到带圆角的正方形制作动画。据我了解,对于流畅的动画,两条路径的点数应该相等。所以我写了一个基于多条弧构建圆的函数: private func circleShape(segmentNu
对于横向和纵向模式,是否可以将元素重置到相同的%位置(距x = 0轴的距离)?如果是的话你能告诉我怎么做吗?另外,由于我是 Swift 的新手,如果您发现任何错误的代码错误,请DO通知我以便得到更好的
我正在尝试在叠加渲染器中使用 UIBezierPath 绘制一些线条。我收到错误 CGContextSetStrokeColorWithColor: invalid context 0x0 我怀疑这是
我想圆化我的右角,但只适用于左角 let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [UIRectCorner.
我想圆化我的右角,但只适用于左角 let path = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [UIRectCorner.
当我尝试平移路径,将其移动到原点 {0, 0} 时,生成的路径边界错误。 (或者,我的假设是错误的)。 例如该路径给出以下边界信息: let bezier = UIBezierPath(cgPath:
我是一名优秀的程序员,十分优秀!