Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/117.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用ObjectiveC中的核心图形,如何围绕圆弯曲箭头?_Ios_Objective C_Core Graphics_Drawrect_Curve - Fatal编程技术网

Ios 使用ObjectiveC中的核心图形,如何围绕圆弯曲箭头?

Ios 使用ObjectiveC中的核心图形,如何围绕圆弯曲箭头?,ios,objective-c,core-graphics,drawrect,curve,Ios,Objective C,Core Graphics,Drawrect,Curve,我们的设计师要求我重新创建: 我正在对UIView进行子类化,我已经覆盖了drawRect命令,如下所示: [super drawRect:frame]; CGFloat x = self.frame.origin.x; CGFloat y = self.frame.origin.y; CGFloat w = self.frame.size.width; CGFloat h = self.frame.size.height; CGFloat lineWidth = lineWidthRequ

我们的设计师要求我重新创建:

我正在对UIView进行子类化,我已经覆盖了drawRect命令,如下所示:

[super drawRect:frame];

CGFloat x = self.frame.origin.x;
CGFloat y = self.frame.origin.y;
CGFloat w = self.frame.size.width;
CGFloat h = self.frame.size.height;
CGFloat lineWidth = lineWidthRequested;
CGPoint centerPoint = CGPointMake(w/2, h/2);
CGFloat radius = radiusRequested;
CGFloat startAngle = 3 * M_PI / 2;
CGFloat endAngle = startAngle + percentage * 2 * M_PI;

CGMutablePathRef arc = CGPathCreateMutable();
CGPathAddArc(arc, NULL,
             centerPoint.x, centerPoint.y,
             radius,
             startAngle,
             endAngle,
             NO);
CGPathRef strokedArc = CGPathCreateCopyByStrokingPath(arc, NULL,
                               lineWidth,
                               kCGLineCapButt,
                               kCGLineJoinMiter, // the default
                               10); // 10 is default miter limit

CGContextRef c = UIGraphicsGetCurrentContext();
CGContextAddPath(c, strokedArc);
CGContextSetFillColorWithColor(c, [UIColor colorWithRed:239/255.0 green:101/255.0 blue:47/255.0 alpha:1.0].CGColor);
CGContextDrawPath(c, kCGPathFill);
我的结局是:

还得画箭头。会很容易的,对吧

在努力记住我的三角后,我在这页上找到了围绕中心旋转的点:

但是当我尝试翻译到目标C来画箭头时,我得到了非常奇怪的结果。下面是drawRect中的代码:

    CGFloat triangle[3][2] = {{centerPoint.x + 10, h - (centerPoint.y + radius)},
    {centerPoint.x, h - (centerPoint.y + radius + lineWidth/2)},
    {centerPoint.x, h - (centerPoint.y + radius - lineWidth/2)}};

for (int idx=0;idx < 3; idx++) {
    // translate to origin
    triangle[idx][0] -= centerPoint.x;
    triangle[idx][1] -= centerPoint.y;
}

CGFloat angDistance = endAngle - startAngle;
CGFloat ct = cos(angDistance);
CGFloat st = sin(angDistance);

for (int idx=0;idx < 3; idx++) {
    // rotate
    triangle[idx][0] = ct * triangle[idx][0] - st * triangle[idx][1];
    triangle[idx][1] = -st * triangle[idx][0] + ct * triangle[idx][1];
}

for (int idx=0;idx < 3; idx++) {
    // translate back to position
    triangle[idx][0] += centerPoint.x;
    triangle[idx][1] += centerPoint.y;
}

NSLog(@"Rotating through %g, %06.1f,%06.1f  , ct - %g, st - %g",angDistance, triangle[0][0],triangle[0][1],ct, st);

// XXX todo draw the filled triangle at end.
// draw a red triangle, the point of the arrow
CGContextSetFillColorWithColor(c, [[UIColor greenColor] CGColor]);
CGContextMoveToPoint(c, triangle[0][0], triangle[0][1]);
CGContextAddLineToPoint(c, triangle[1][0], triangle[1][1]);
CGContextAddLineToPoint(c, triangle[2][0], triangle[2][1]);
CGContextFillPath(c);
CGFloat三角形[3][2]={{centerPoint.x+10,h-(centerPoint.y+radius)},
{centerPoint.x,h-(centerPoint.y+半径+线宽/2)},
{centerPoint.x,h-(centerPoint.y+半径-线宽/2)};
for(intidx=0;idx<3;idx++){
//翻译成原文
三角形[idx][0]=中心点.x;
三角形[idx][1]=中心点y;
}
CgDistance=端角-星形缠结;
CGFloat ct=cos(距离);
CGFloat st=sin(距离);
for(intidx=0;idx<3;idx++){
//轮换
三角形[idx][0]=ct*三角形[idx][0]-st*三角形[idx][1];
三角形[idx][1]=-st*三角形[idx][0]+ct*三角形[idx][1];
}
for(intidx=0;idx<3;idx++){
//回位
三角形[idx][0]+=中心点.x;
三角形[idx][1]+=中心点y;
}
NSLog(@“旋转通过%g,%06.1f,%06.1f,ct-%g,st-%g”,距离,三角形[0][0],三角形[0][1],ct,st);
//XXX todo在末端绘制填充三角形。
//画一个红色三角形,箭头的点
CGContextSetFillColorWithColor(c,[[UIColor-greenColor]CGColor]);
CGContextMoveToPoint(c,三角形[0][0],三角形[0][1]);
CGContextAddLineToPoint(c,三角形[1][0],三角形[1][1]);
CGContextAddLineToPoint(c,三角形[2][0],三角形[2][1]);
CGContextFillPath(c);
我本以为我会做这些点,然后把它们转换成原点,旋转,然后再把它们转回来,我会笑的

然而,事实并非如此……当百分比从0增加到2pi时,箭头以模糊的三角形路径绘制自己。当距离为零或pi时,箭头位于正确的位置。当我指向pi/2或3pi/2时,箭头指向封闭矩形的下角

我一定是在做一些非常愚蠢的事情,但我一辈子都看不到

有什么想法吗

谢谢


-Ken

我建议为所需形状的整个轮廓构建一条路径,然后用所需颜色“填充”该路径。这消除了任何缺口或不完全对齐的风险

因此,此路径可能包含箭头外侧的圆弧、箭头头部的两条直线、箭头内侧的弧背,然后闭合该路径。这可能看起来像:

- (void)drawRect:(CGRect)rect {
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, self.arrowColor.CGColor);

    CGPoint center = CGPointMake(rect.size.width / 2.0, rect.size.height / 2.0);

    CGContextMoveToPoint(context, center.x + cosf(self.startAngle) * (self.radius + self.lineWidth / 2.0),
                                  center.y + sinf(self.startAngle) * (self.radius + self.lineWidth / 2.0));

    CGContextAddArc(context, center.x, center.y, self.radius + self.lineWidth / 2.0, self.startAngle, self.endAngle, !self.clockwise);

    CGFloat theta = asinf(self.lineWidth / self.radius / 2.0) * (self.clockwise ? 1.0 : -1.0);
    CGFloat pointDistance = self.radius / cosf(theta);

    CGContextAddLineToPoint(context, center.x + cosf(self.endAngle + theta) * pointDistance,
                                     center.y + sinf(self.endAngle + theta) * pointDistance);

    CGContextAddLineToPoint(context, center.x + cosf(self.endAngle) * (self.radius - self.lineWidth / 2.0),
                                     center.y + sinf(self.endAngle) * (self.radius - self.lineWidth / 2.0));

    CGContextAddArc(context, center.x, center.y, self.radius - self.lineWidth / 2.0, self.endAngle, self.startAngle, self.clockwise);

    CGContextClosePath(context);

    CGContextDrawPath(context, kCGPathFill);
}
这里唯一的诀窍就是在箭的末端找到正确的点。我已经改进了处理更胖箭头的选择,但是您应该可以随意使用您认为最适合您的应用程序的任何东西

因此,以下代码:

self.arrowView.radius = 100;
self.arrowView.arrowColor = [UIColor blueColor];
self.arrowView.lineWidth = 40;
self.arrowView.startAngle = -M_PI_2;
self.arrowView.endAngle = M_PI;
self.arrowView.clockwise = TRUE;
将产生以下内容(我正在使用
CADisplayLink
制作动画):

这使用了零的起始角作为“3点钟”位置的意思,但是您可以根据自己的需要对其进行调整。但希望它能说明解决问题的一种方法

顺便说一下,虽然我已经回答了如何使用CoreGraphics实现这一点的问题,但我不一定建议这样做。例如,在中,我没有实现
drawRect
,而是更新
CAShapeLayer
。通过这样做,我不仅可以避免
drawRect
效率低下,而且理论上还可以改变您使用该
CAShapeLayer
的方式(例如,对于某些
UIView
,将其用作
遮罩,显示其背后更有趣的颜色渐变(或其他图像)。

这里是另一个解决方案(虽然不是很可扩展)。此解决方案假设这就像一个徽标,其中绘制的圆的角度/百分比不会改变

- (void)drawRect:(CGRect)rect {
    UIBezierPath *circleOutline = [UIBezierPath bezierPath];

    [self.circleColor setStroke];
    [circleOutline setLineWidth:self.bounds.size.width*0.15];
    [circleOutline addArcWithCenter:CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2) radius:self.bounds.size.width/2-circleOutline.lineWidth/2 startAngle:3*M_PI/2 endAngle:3*M_PI/4 clockwise:YES];
    [circleOutline stroke];

    [self addArrowView:circleOutline];
}

- (void)addArrowView:(UIBezierPath *)path {
    for (int x = 0; x < self.bounds.size.width/2; x++) {
        for (int y = self.bounds.size.height/2; y < self.bounds.size.height; y++) {
            if ([path containsPoint:CGPointMake(x, y)]) {

                // Pythagorean Theorem - We want the diagonal length of the square to be lineWidth, so we need to calculate what size
                // to make each side of the square to make the diagonal equal to lineWidth
                double sideLength = sqrt((path.lineWidth*path.lineWidth)/2);

                UIView *arrowView = [[UIView alloc] initWithFrame:CGRectMake(x-sideLength/2, y-sideLength/2, sideLength, sideLength)];
                arrowView.backgroundColor = self.circleColor;
                [self addSubview:arrowView];

                return;
            }
        }
    }
}
-(void)drawRect:(CGRect)rect{
UIBezierPath*circleOutline=[UIBezierPath bezierPath];
[自循环颜色设定行程];
[circleOutline设置线宽:self.bounds.size.width*0.15];
[circleOutline addArcWithCenter:CGPointMake(self.bounds.size.width/2,self.bounds.size.height/2)半径:self.bounds.size.width/2-circleOutline.lineWidth/2 startAngle:3*M_PI/2端角:3*M_PI/4顺时针:是];
[圆形轮廓笔划];
[自添加箭头视图:圆形轮廓];
}
-(无效)添加箭头视图:(UIBezierPath*)路径{
对于(int x=0;x
将产生:


你可能会感兴趣。哇,谢谢!那太完美了。如果你到了英格兰的橄榄球队,我很乐意为你买一杯啤酒!免费啤酒总是一个很好的姿态。也许你应该添加一个功能,向回答正确的人免费送啤酒钱。我用你的解决方案画了另一种圆形箭头。只是做了一些使用CGContextAddLineToPoint时调整角度和半径。