, становится огромное количество). Использование правильного шрифта позволяет избежать этих проблем.

го бился головой о стену, пытаясь понять, почему это не работает.

По сути, я пытаюсь построить график (диаграмму) с помощью CGPath, а затем использовать его для обрезки градиента. Конечный эффект должен быть похож на приложение Stocks, которое поставляется с iPhone.

Градиент и траектория хорошо рисуются отдельно в виде двухслойных (незарезанных) элементов. Но если я закомментирую CGContextDrawPath, ни линия, ни градиент не появятся на экране.

Вот мой код drawRect:

CGContextRef context = UIGraphicsGetCurrentContext();

[[UIColor whiteColor] set];
CGContextSetLineWidth(context, 2.0f);
CGPoint lastDrawnPt = [[points objectAtIndex:0] CGPointValue];
CGPoint firstDrawnPt = lastDrawnPt;
//create the path for the gradient
CGMutablePathRef thePath = CGPathCreateMutable();
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom left
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);


for (int i=0; i<(points.count-1); i++) {
    //CGPoint pt1 = [[points objectAtIndex:i] CGPointValue];
    CGPoint pt2 = [[points objectAtIndex:i+1] CGPointValue];
    if (pt2.x > lastDrawnPt.x+2) {
        // only draw if we've moved sunstantially to the right

        //for the gradient
        CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
        CGPathAddLineToPoint(thePath, NULL, pt2.x, pt2.y);


        lastDrawnPt = pt2;
    }
}

//finish the gradient clipping path
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height);, // bottom right
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height);
CGPathAddLineToPoint(thePath, NULL, firstDrawnPt.x, self.bounds.size.height); // bottom right

CGPathCloseSubpath(thePath);

//add the gradient clipping path to the context
CGContextSaveGState(context);
CGContextAddPath(context, thePath);

//draw the path
float components[4] = {1.0, 1.0, 1.0, 1.0};
CGContextSetStrokeColor(context, components);
CGContextDrawPath(context,kCGPathStroke);

//clip the path
CGContextClip(context);


//Draw Gradient
UIColor *topColor = [UIColor colorWithRed: 1.0 green:1.0 blue:1.0 alpha:1.0];
UIColor *bottomColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.0];
CGColorRef colorRef[] = { [topColor CGColor], [bottomColor CGColor] };
CFArrayRef colors = CFArrayCreate(NULL, (const void**)colorRef, sizeof(colorRef) / sizeof(CGColorRef), &kCFTypeArrayCallBacks);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colors, NULL);
CFRelease(colorSpace);
CFRelease(colors);

//  Draw a linear gradient from top to bottom
CGPoint gradStartPoint = CGPointMake(50.0, self.bounds.size.height);
CGPoint gradEndPoint = CGPointMake(50.0, 0.0);
CGContextDrawLinearGradient(context, gradient, gradStartPoint, gradEndPoint, 0);

CFRelease(gradient);

// Cleanup
CGColorSpaceRelease(colorSpace);

CGContextRestoreGState(context);
 omz26 янв. 2011 г., 02:18
Не могли бы вы привести пример того, что содержит массив points?
 namar0x030926 янв. 2011 г., 00:18
Вы пробовали CGContextFlush или CGContextSynchronize ... Я думаю, что это может быть связано с наслоением. Также попробуйте переместить CGContextClip после прорисовки градиента ...
 avance26 янв. 2011 г., 00:28
Спасибо за идеи, но они, похоже, не помогли.
 avance26 янв. 2011 г., 01:35
Когда я изменяю линию пути рисования на CGContextDrawPath (context, kCGPathFillStroke); Это вообще не заполняет путь ... это ключ?
 avance26 янв. 2011 г., 01:33
Я начинаю думать, что что-то не так с тем, как я строю свой путь.

Ответы на вопрос(1)

Решение Вопроса
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom left
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);


for (int i=0; i<(points.count-1); i++) {
    //CGPoint pt1 = [[points objectAtIndex:i] CGPointValue];
    CGPoint pt2 = [[points objectAtIndex:i+1] CGPointValue];
    if (pt2.x > lastDrawnPt.x+2) {
        // only draw if we've moved sunstantially to the right

        //for the gradient
        CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
        CGPathAddLineToPoint(thePath, NULL, pt2.x, pt2.y);


        lastDrawnPt = pt2;
    }
}

//finish the gradient clipping path
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y);
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom right
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height);
CGPathAddLineToPoint(thePath, NULL, firstDrawnPt.x, self.bounds.size.height); // bottom right

может выглядеть примерно так:

| |||| |

Он не отображает одну непрерывную форму. Таким образом, этот путь бесполезен для отсечения, поскольку он фактически пуст; как вы видели, отсечение к нему не приведет к дальнейшему рисованию внутри обтравочного контура.

каждыйlineto, curveto, arcи т. д. работает с текущей точки. Вы устанавливаете этопервоначально с участиемmoveto, но каждыйlineto, curveto, arcи т. д. неЧисто текущая точка, этообновления Это. Таким образом, чтобы создать одну фигуру, вы делаете одинmoveto с последующей последовательностьюlineto (или жеcurveto или жеarc) с последующимclosepath.

Говоря оclosepath

CGPathCloseSubpath(thePath);

Это создает единственную замкнутую фигуру в контуре, но, поскольку эта фигура имеет нулевую область (будучи только отрезком линии, который удваивается обратно на себя), она все равно не помогает в целях отсечения.

Я подозреваю, что все, что вам нужно сделать, это вырезать хотя бы один изmoveto сегменты (один в цикле, если не еще один после него). Затем вы можете упростить цикл - использовать быстрое перечисление в массиве вместо индексов и вырезать отслеживание «последней нарисованной точки».

Кроме того, правильный тип для индексов в NSArrayNSUIntegerнеint, Следите за тем, чтобы ваши типы соответствовали друг другу - это позволит избежать боли в будущем.

 Peter Hosey26 янв. 2011 г., 20:29
@juggleware: нет, язык делает, но это не значит, что вы не должны использовать правильный тип в первую очередь. Если вы используете неправильный тип, вы можете оказаться не в состоянии рассчитывать достаточно далеко или считать слишком далеко (последний в случае переполнения в отрицательный диапазон, который при приведении к типу без знака, какNSUInteger, становится огромное количество). Использование правильного шрифта позволяет избежать этих проблем.
 avance26 янв. 2011 г., 18:15
Большое спасибо, Питер! Вот и все. У меня было опасно умеренное понимание того, как работает CGPath.
 avance26 янв. 2011 г., 18:44
Что касается NSUInteger против int в [NSArray objectAtIndex: i], разве метод не автоматически преобразует int в NSUInteger?

Ваш ответ на вопрос