I want to label every part of the following curve like in the figure. The label origin should start from the middle of the curve segment see the graphic. I think that something is not quite right in my logic. Could you assist where is the error in my code? I think that the code and the figure explain itself.

Thanks for your time and help!

    CGFloat radius = self.height / 3.2f; // radius of the curve
    CGPoint center = CGPointMake(self.width / 2.f, self.height / 2.f); //center of the curve
    UIBezierPath* circlePath = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:degreesToRadian(270.f) endAngle:DEGREES_TO_RADIANS(269.999f) clockwise:YES]; // go around like the clock

    CGFloat strokeStart = 0.f;
    // Add the parts of the curve to the view
    for (int i = 0; i < segmentValues.count; i++) {
        NSNumber *value = [segmentValues objectAtIndex:i];
        CGFloat strokeEnd = [value floatValue] / kPercentHundred;

        CAShapeLayer *circle = [CAShapeLayer layer];
        circle.path          = circlePath.CGPath;
        circle.lineCap       = kCALineCapButt;
        circle.fillColor     = [UIColor clearColor].CGColor;
        circle.strokeColor   = [[colors objectAtIndex:i] CGColor];
        circle.lineWidth     = kWidhtLine;
        circle.zPosition     = 1.f;
        circle.strokeStart   = strokeStart;
        circle.strokeEnd     = strokeStart + strokeEnd;
        [self.layer addSublayer:circle];

        UIView *example = [[UIView alloc] init];
        example.backgroundColor = kColorRed;
        example.size = CGSizeMake(10, 10);
        // middle = "(circle.strokeStart + circle.strokeEnd) / 2.f"
        // * convert percent to degree
        CGFloat angle = (circle.strokeStart + circle.strokeEnd) / 2.f * 360.f;
        // determine the point and add the right offset
        example.origin = CGPointMake(cosf(angle) * radius + center.x, sinf(angle) * radius + center.y);
        [self addSubview:example];

        strokeStart = circle.strokeEnd;
    }

What I get see the figure. What I got

What I expect in concept is something similar to the following figure.

enter image description here

有帮助吗?

解决方案

There are two key issues:

  1. You calculate the angle via:

    CGFloat angle = (circle.strokeStart + circle.strokeEnd) / 2.f * 360.f;
    

    You then proceed to use that for the cos and sin functions. Those expect radian values, though, so you have to convert this to radians before you use it in those functions. Thus, yielding:

    CGFloat angle = degreesToRadian((circle.strokeStart + circle.strokeEnd) / 2.f * 360.f);
    

    (BTW, I don't know if you prefer degreesToRadian or DEGREES_TO_RADIANS, but you should probably use one or the other.)

    Or, more simply, you can convert to radians directly:

    CGFloat angle = (circle.strokeStart + circle.strokeEnd) / 2.f * M_PI * 2.0;
    
  2. You have rotated the circle 90 degrees (presumably so that it would start a "12 o'clock" rather than "3 o'clock"). Well, if you rotate the circle, then you have to rotate angle when you calculate where to put your example view, as well:

    example.center = CGPointMake(cosf(angle - M_PI_2) * radius + center.x, sinf(angle - M_PI_2) * radius + center.y);
    

This yields:

enter image description here

其他提示

I'm not sure what your goal is. You say you want to create labels, but what you create in your code is generic UIView objects.

Then you are setting a property "origin" on the view, but UIView does not have an origin as far as I know. It has a frame, which has an origin component, but not an origin property. I'm guessing that the code you posted is not actual, running code.

Do you want the labels to be centered on top of the circle? If so, you should both set the text alignment to NSTextAlignmentCenter, and set the center property of the views rather than the frame.origin.

I have a working sample project on github that creates an analog clock and puts labels for the hours around it. You can look at the code for an idea of how to do it:

Analog clock sample project

(The project also shows how to use the new spring physics UIView animation method.)

hmm it i a little late for me ;)

I think you have to use UIView::setCenter this will solve you problem. Then the center of the view is on your circle.

Edit: And it is easier to manipulate the position.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top