【问题标题】:Label curve segments标记曲线段
【发布时间】:2014-03-19 21:32:24
【问题描述】:

我想像图中一样标记以下曲线的每个部分。标签原点应从曲线段的中间开始,见图。我认为在我的逻辑中有些事情不太正确。您能否帮助我的代码中的错误在哪里?我认为代码和数字说明了自己。

感谢您的宝贵时间和帮助!

    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;
    }

我看到的数字。

我期望的概念类似于下图。

【问题讨论】:

  • 您的角度计算看起来不正确。 strokeStart 和 strokeEnd 应该是从 0 到 1 的值。因此,如果要将它们转换为角度,则应使用 (strokeStart+strokeEnd)/2 * 2 * M_PI,简化为 (strokeStart+strokeEnd) * M_PI (角度以弧度表示,范围从 0 到 2 pi,而不是 0 到 360。)
  • 是的,你是对的,非常感谢。我还添加了这个“degreesToRadian(270.f)”到角度,现在它可以工作了。您能否将评论移至您的答案?

标签: ios objective-c geometry computational-geometry


【解决方案1】:

有两个关键问题:

  1. 您通过以下方式计算角度:

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

    然后您继续将其用于cossin 函数。但是,那些期望弧度值,因此您必须先将其转换为弧度,然后才能在这些函数中使用它。因此,产生:

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

    (顺便说一句,我不知道你更喜欢degreesToRadian 还是DEGREES_TO_RADIANS,但你应该使用其中一个。)

    或者,更简单地说,您可以直接转换为弧度:

    CGFloat angle = (circle.strokeStart + circle.strokeEnd) / 2.f * M_PI * 2.0;
    
  2. 您已将圆圈旋转了 90 度(大概是为了让它开始“12 点钟”而不是“3 点钟”)。好吧,如果您旋转圆圈,那么在计算 example 视图的放置位置时,您还必须旋转 angle

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

这会产生:

【讨论】:

    【解决方案2】:

    我不确定你的目标是什么。你说你想创建标签,但你在代码中创建的是通用 UIView 对象。

    然后您在视图上设置属性“原点”,但据我所知 UIView 没有原点。它有一个框架,它有一个原点组件,但没有原点属性。我猜您发布的代码不是实际的运行代码。

    您希望标签居中在圆的顶部吗?如果是这样,您应该将文本对齐设置为 NSTextAlignmentCenter,并设置视图的 center 属性而不是 frame.origin。

    我在 github 上有一个工作示例项目,它创建了一个模拟时钟并为它周围的几个小时放置标签。您可以查看代码以了解如何操作:

    Analog clock sample project

    (该项目还展示了如何使用新的spring物理UIView动画方法。)

    【讨论】:

    • 我从 xcode 复制了代码,所以它正在运行。我想像你在上图中看到的那样放置标签。感谢您的项目和回答,我现在去检查一下。
    • 那么什么是origin属性呢?法律法规如何?
    • 对不起,我没有提到。我在 UIView 上编写了一个类别,并实现了一些有用的方法,例如设置原点、大小、x、y、.. 等
    • 重要信息。您应该改用 center 属性,并确保将标签设置为居中。为什么你的代码添加了空白的 UIViews,但是你的图像显示了红色块和文本标签?同样,您显示的图像与代码不匹配。
    【解决方案3】:

    嗯,我有点晚了;)

    我认为你必须使用 UIView::setCenter 这将解决你的问题。然后视图的中心就在你的圆圈上。

    编辑:而且更容易操纵位置。

    【讨论】:

    • 也许我对这个问题的解释是错误的,但这个解决方案与我的问题相去甚远,但感谢您花时间回答我的问题。
    猜你喜欢
    • 1970-01-01
    • 2021-09-16
    • 2011-11-05
    • 2019-06-28
    • 2017-05-23
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 2013-10-27
    相关资源
    最近更新 更多