Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.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 剪辑CGPath并用两种不同的颜色填充_Ios_Objective C_Drawing_Core Graphics - Fatal编程技术网

Ios 剪辑CGPath并用两种不同的颜色填充

Ios 剪辑CGPath并用两种不同的颜色填充,ios,objective-c,drawing,core-graphics,Ios,Objective C,Drawing,Core Graphics,我正在创建一个自定义的“星形”控件,因为您可以将一个浮点数传递到控件中,因为评级为2.5,5颗星中的2.5颗星将为红色,其余为灰色 我正在用一个有5个点的UIBezierPath来画星星,这非常好用。然而,当我使用浮点数时,我需要确保小数被考虑在内。我认为实现这一点的最佳方法是将贝塞尔路径裁剪到最终宽度的一部分,然而,这种方法似乎对图形本身没有任何影响;星星是按正常方式绘制的,不考虑小数 正如您可能期望我所说的,我实际上才刚刚开始涉足CoreGraphics,我想解释一下为什么我的方法不起作用,

我正在创建一个自定义的“星形”控件,因为您可以将一个浮点数传递到控件中,因为评级为2.5,5颗星中的2.5颗星将为红色,其余为灰色

我正在用一个有5个点的UIBezierPath来画星星,这非常好用。然而,当我使用浮点数时,我需要确保小数被考虑在内。我认为实现这一点的最佳方法是将贝塞尔路径裁剪到最终宽度的一部分,然而,这种方法似乎对图形本身没有任何影响;星星是按正常方式绘制的,不考虑小数

正如您可能期望我所说的,我实际上才刚刚开始涉足CoreGraphics,我想解释一下为什么我的方法不起作用,以及一种修复方法,以帮助我在框架中取得进展

期待听到一些回应

- (void)drawStarsWithRating:(float)rating maxRating:(float)maxRating yOrigin:(CGFloat)yOrigin inContext:(CGContextRef)context {
    float width = MKRGlyphSize;

    CGFloat xCenter = MKRLeftBorderPadding + (0.5 * width);
    CGFloat yCenter = yOrigin + (0.5 * width);

    double r = width / 2.0;
    float flip = -1.0;

    for (NSUInteger i = 0; i < maxRating; i++) {
        CGContextSaveGState(context);
        if (i < rating) {
            if (self.selected) {
                CGContextSetFillColorWithColor(context, RGB(125, 212, 67).CGColor);
            }
            else {
                CGContextSetFillColorWithColor(context, RGB(215, 35, 32).CGColor);
            }
        }
        else {
            if (self.selected) {
                CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
            }
            else {
                CGContextSetFillColorWithColor(context, RGB(178, 178, 178).CGColor);
            }
        }

        double theta = 2.0 * M_PI * (2.0 / 5.0);
        UIBezierPath *bezier = [UIBezierPath bezierPath];
        [bezier moveToPoint:CGPointMake(xCenter, r * flip + yCenter)];

        for (NSUInteger k = 1; k < 5; k++) {
            float x = r * sin(k * theta);
            float y = r * cos(k * theta);
            [bezier addLineToPoint:CGPointMake(x + xCenter, y * flip + yCenter)];
        }
        [bezier setLineWidth:1.0f];
        [bezier setLineJoinStyle:kCGLineJoinMiter];
        [bezier closePath];
        [bezier fill];
        if (rating - floorf(rating) > 0) {
            CGRect clipRect = CGRectMake(xCenter, yOrigin, width * (rating - floorf(rating)), width);
            CGContextClipToRect(context, clipRect);
        }
        xCenter += width;
        CGContextRestoreGState(context);
    }
}

我注意到的一个问题是,你只在这条路上[填充]一次。这意味着对于分数恒星,你只能看到恒星的一半,而不能看到另一半。在下面的代码中,每个星号都用白色填充,如果星号的任何部分在评级范围内,那么它将再次用蓝色填充

我还注意到,您使用的剪切矩形从xCenter开始,而不是从星形的左侧开始

我还稍微调整了一下数学,以更一致地计算每颗星的填充百分比

 - (void)drawStarsWithRating:(float)rating maxRating:(float)maxRating yOrigin:(CGFloat)yOrigin inContext:(CGContextRef)context {
    float width = MKRGlyphSize;

    CGFloat xCenter = MKRLeftBorderPadding + (0.5 * width);
    CGFloat yCenter = yOrigin + (0.5 * width);

    double r = width / 2.0;
    float flip = -1.0;

    for (NSUInteger i = 0; i < maxRating; i++) {
        CGContextSaveGState(context);

        // for clarity, i removed the colors from the top
        // and ignore selected state. i use blue/white
        // colors hard coded below
        //
        // you can easily change those colors just as you
        // had before

        // create star path
        double theta = 2.0 * M_PI * (2.0 / 5.0);
        UIBezierPath *bezier = [UIBezierPath bezierPath];
        [bezier moveToPoint:CGPointMake(xCenter, r * flip + yCenter)];
        for (NSUInteger k = 1; k < 5; k++) {
            float x = r * sin(k * theta);
            float y = r * cos(k * theta);
            [bezier addLineToPoint:CGPointMake(x + xCenter, y * flip + yCenter)];
        }
        [bezier setLineWidth:1.0f];
        [bezier setLineJoinStyle:kCGLineJoinMiter];
        [bezier closePath];

        // fill background of star with white
        [[UIColor whiteColor] setFill];
        [bezier fill];

        // calculate the percentage of this star
        // that we should fill
        CGFloat currStar = i;
        CGFloat percentOfStar;
        if(rating > currStar){
            // at least some of the star should be filled
            percentOfStar = rating - currStar > 0 ? rating - currStar : 0;
            percentOfStar = percentOfStar > 1 ? 1 : percentOfStar;
        }else{
            // none of the star should be filled
            percentOfStar = 0;
        }
        if (percentOfStar) {
            // if we need at least a little filling, then clip to that % of the star
            // notice (xCenter - .5*width) to align the clipRect to the left side of
            // the star.
            // now fill the selected portion of the star with blue
            CGRect clipRect = CGRectMake(xCenter - .5*width, yOrigin, width * (percentOfStar), width);
            CGContextClipToRect(context, clipRect);
            [[UIColor blueColor] setFill];
            [bezier fill];
        }
        xCenter += width;
        CGContextRestoreGState(context);
    }
}

你可以稍微改变一下:

用背景色填充视图的背景

使用percentOfStar创建反映评级的矩形路径


使用星形路径进行剪裁

使用绘图是过分的。除非你这样做是为了提高你的技能,否则我建议你使用许多可用的星级控制之一。如果您是自己做的,请远离绘图,这不是正确的方法。控件将位于自定义绘制的表视图单元格中,因此不幸的是,这是唯一的方法不,您仍然可以在不绘图的情况下使其工作。这是一种糟糕的方法,在绘制其他所有内容时,没有必要将控件添加为子视图。这就是为什么它是注释。