iOS. Приемы программирования Нахавандипур Вандад

CGFloat *startColorComponents =

(CGFloat *)CGColorGetComponents([startColor CGColor]);

UIColor *endColor = [UIColor blueColor];

CGFloat *endColorComponents =

(CGFloat *)CGColorGetComponents([endColor CGColor]);

CGFloat colorComponents[8] = {

/* Четыре компонента оранжевого цвета (RGBA (RGBA) */

startColorComponents[0],

startColorComponents[1],

startColorComponents[2],

startColorComponents[3], /* Первый цвет = оранжевый */

/* Четыре компонента голубого цвета (RGBA) */

endColorComponents[0],

endColorComponents[1],

endColorComponents[2],

endColorComponents[3], /* Второй цвет = голубой */

};

CGFloat colorIndices[2] = {

0.0f, /* Цвет 0 в массиве colorComponents */

1.0f, /* Цвет 1 в массиве colorComponents */

};

CGGradientRef gradient = CGGradientCreateWithColorComponents

(colorSpace,

(const CGFloat *)&colorComponents,

(const CGFloat *)&colorIndices,

2);

CGColorSpaceRelease(colorSpace);

CGPoint startPoint, endPoint;

startPoint = CGPointMake(120,

260);

endPoint = CGPointMake(200.0f,

220);

CGContextDrawLinearGradient (currentContext,

gradient,

startPoint,

endPoint,

kCGGradientDrawsBeforeStartLocation |

kCGGradientDrawsAfterEndLocation);

CGGradientRelease(gradient);

CGContextRestoreGState(currentContext);

}

Возможно, вам не совсем понятно, как при смешивании значений kCGGradientDrawsBeforeStartLocation и kCGGradientDrawsAfterEndLocation, переданных процедуре CGContextDrawLinearGradient, получается диагональный эффект, как на рис. 17.28. Поэтому уберем эти значения и зададим для этого параметра процедуры CGContextDrawLinearGradient значение 0 — как и раньше. Результат получится как на рис. 17.29.

Рис. 17.29. Осевой градиент без распространения цветов

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

См. также

Раздел 17.3.

17.11. Перемещение фигур, нарисованных в графических контекстах

Постановка задачи

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

Решение

Воспользуйтесь функцией CGAffineTransformMakeTranslation для создания аффинного преобразования сдвига.

Обсуждение

В разделе 17.8 было упомянуто о преобразованиях. Преобразование — это, в сущности, просто изменение способа отображения рисунка. Преобразования в Core Graphics — это объекты, применяемые к фигурам перед отрисовкой последних. Например, можно создать преобразование сдвига (Translation Transformation). «Сдвига чего?» — могли бы спросить вы. Дело в том, что преобразование сдвига — это механизм, позволяющий сместить фигуру или графический контекст.

Среди других типов преобразований следует также назвать вращение (см. раздел 17.13) и масштабирование (см. раздел 17.12). Все это примеры аффинных преобразований, то есть при таком преобразовании каждая точка оригинала сопоставляется с другой точкой в окончательной версии. Все преобразования, о которых мы будем говорить в этой книге, являются аффинными.

В ходе преобразования сдвига актуальное положение фигуры на пути или в графическом контексте сдвигается на другую относительную позицию. Например, если вы поставите точку с координатами (10; 20), примените к ней преобразование сдвига (30; 40) и снова ее поставите, точка окажется расположенной в координатах (40; 60), поскольку 40 = 10 + 30, а 60 = 20 + 40.

Чтобы создать новое преобразование сдвига, используется функция CGAffineTransformMakeTranslation, которая возвращает аффинное преобразование типа CGAffineTransform. Два параметра этой функции указывают сдвиг по осям X и Y в точках.

В разделе 17.8 мы изучили, что процедура CGPathAddRect принимает в качестве второго параметра объект преобразования типа CGAffineTransform. Чтобы сместить прямоугольник с его исходной позиции на другую, можно просто создать аффинное преобразование, указывающее изменения, которые вы хотели бы применить к координатам x и y, и передать преобразование второму параметру процедуры CGPathAddRect, как показано далее:

— (void)drawRect:(CGRect)rect{

/* Сначала создаем путь. Просто описатель пути. */

CGMutablePathRef path = CGPathCreateMutable();

/* Это границы прямоугольника. */

CGRect rectangle = CGRectMake(10.0f,

10.0f,

200.0f,

300.0f);

/* Мы хотим сместить прямоугольник на 100 точек вправо,

не изменив при этом его положения по оси Y. */

CGAffineTransform transform = CGAffineTransformMakeTranslation(100.0f,

0.0f);

/* Добавляем прямоугольник к пути. */

CGPathAddRect(path,

&transform,

rectangle);

/* Получаем описатель текущего контекста. */

CGContextRef currentContext =

UIGraphicsGetCurrentContext();

/* Добавляем путь к контексту. */

CGContextAddPath(currentContext,

path);

/* Задаем голубой в качестве цвета заливки. */

[[UIColor colorWithRed:0.20f

green:0.60f

blue:0.80f

alpha:1.0f] setFill];

/* Задаем для обводки коричневый цвет. */

[[UIColor brownColor] setStroke];

/* Задаем для ширины (обводки) значение 5. */

CGContextSetLineWidth(currentContext,

5.0f);

/* Проводим путь в контексте и применяем к нему заливку. */

CGContextDrawPath(currentContext,

kCGPathFillStroke);

/* Избавляемся от пути. */

CGPathRelease(path);

}

На рис. 17.30 показан результат выполнения этого блока кода внутри объекта-вида.

Сравните рис. 17.30 и 17.22. Видите разницу? Еще раз просмотрите исходный код для обеих фигур и убедитесь в том, что положения по осям X и Y, указанные для обоих прямоугольников, в обоих блоках кода идентичны. Различие заключается только в том, что на рис. 17.30 мы видим результат применения к прямоугольнику аффинного преобразования, когда прямоугольник добавляется к пути.

Кроме применения преобразований к фигурам, отрисовываемым относительно путей, мы можем применять преобразования и к графическому контексту с помощью процедуры CGContextTranslateCTM. Она применяет преобразование к текущей матрице преобразований (Current Transformation Matrix, CTM). Хотя это название и может показаться сложным, понять его смысл не составляет труда. Считайте CTM правилами, определяющими расположение центра вашего графического контекста, а также правилами проецирования каждой отрисовываемой точки на экране. Например, если вы приказываете Core Graphics поставить точку с координатами (0; 0), Core Graphics найдет центр экрана, получив эту информацию из текущей матрицы преобразований. Затем CTM выполнит определенные вычисления и сообщит Core Graphics, что искомая точка расположена в верхнем левом углу экрана. С помощью таких процедур, как CGContextTranslateCTM, можно изменить конфигурацию этой матрицы, после чего заставить все фигуры, отрисованные в графическом контексте, занять на холсте другие позиции. Вот пример, в котором мы достигаем точно такого же эффекта, как и на рис. 17.30, но применяем преобразование сдвига не к самому прямоугольнику, а к текущей матрице преобразований:

Рис. 17.30. Прямоугольник с аффинным преобразованием сдвига

— (void)drawRect:(CGRect)rect{

/* Сначала создаем путь. Просто описатель пути. */

CGMutablePathRef path = CGPathCreateMutable();

/* Это границы прямоугольника. */

CGRect rectangle = CGRectMake(10.0f,

10.0f,

200.0f,

300.0f);

/* Добавляем прямоугольник к пути. */

CGPathAddRect(path,

NULL,

rectangle);

/* Получаем описатель текущего контекста. */

CGContextRef currentContext = UIGraphicsGetCurrentContext();

/* Сохраняем состояние контекста, чтобы позже

можно было восстановить это состояние. */

CGContextSaveGState(currentContext);

/* Сдвигаем текущую матрицу преобразований

на 100 точек вправо. */

CGContextTranslateCTM(currentContext,

100.0f,

0.0f);

/* Добавляем путь к контексту. */

CGContextAddPath(currentContext,

path);

/* Задаем голубой в качестве цвета заливки. */

[[UIColor colorWithRed:0.20f

green:0.60f

blue:0.80f

alpha:1.0f] setFill];

/* Задаем для обводки коричневый цвет. */

[[UIColor brownColor] setStroke];

/* Задаем для ширины (обводки) значение 5. */

CGContextSetLineWidth(currentContext,

5.0f);

/* Проводим путь в контексте и применяем к нему заливку. */

CGContextDrawPath(currentContext,

kCGPathFillStroke);

/* Избавляемся от пути. */

CGPathRelease(path);

/* Восстанавливаем состояние контекста. */

CGContextRestoreGState(currentContext);

}

Запустив эту программу, вы получите точно такие же результаты, как и на рис. 17.30.

См. также

Разделы 17.8, 17.12 и 17.13.

17.12. Масштабирование фигур, нарисованных в графических контекстах

Постановка задачи

Требуется динамически масштабировать фигуры, отрисованные в графическом контексте, в сторону уменьшения или увеличения.

Решение

Создайте аффинное преобразование масштаба, воспользовавшись функцией CGAffineTransformMakeScale.

Обсуждение

В разделе 17.11 было объяснено, что такое преобразование и как применять его к фигурам и графическим контекстам. Один из вариантов преобразования, которым вы можете воспользоваться, — это масштабирование. Core Graphics позволяет без проблем масштабировать фигуру, например круг, на 100 % относительно ее исходного размера.

Чтобы создать аффинное преобразование масштаба, пользуйтесь функцией CGAffineTransformMakeScale, которая возвращает объект преобразования типа CGAffineTransform. Если вы хотите применить преобразование масштаба непосредственно к графическому контексту, примените процедуру CGContextScaleCTM, которая масштабирует CTM. Подробнее о CTM (текущей матрице преобразований) рассказано в разделе 17.11.

Функции преобразования масштаба принимают два параметра: масштабирование по оси X и масштабирование по оси Y. Еще раз обратимся к прямоугольнику с рис. 17.22. Если мы хотим масштабировать этот прямоугольник, чтобы его исходные длина и ширина уменьшились вполовину, то можно просто масштабировать по оси X и Y на 0,5 (вполовину от исходного значения), как показано здесь:

/* Масштабируем прямоугольник, уменьшая его на половину. */

CGAffineTransform transform =

CGAffineTransformMakeScale(0.5f, 0.5f);

/* Добавляем прямоугольник к пути. */

CGPathAddRect(path,

&transform,

rectangle);

На рис. 17.31 показано, что получится, когда мы применим преобразование масштаба к коду, написанному в разделе 17.8.

Рис. 17.31. Масштабирование прямоугольника

Дополнительно к функции CGAffineTransformMakeScale можно использовать процедуру CGContextScaleCTM, помогающую применить преобразование масштаба к графическому контексту. Следующий код даст тот же эффект, что и в предыдущем примере (вновь обратите внимание на рис. 17.31):

— (void)drawRect:(CGRect)rect{

/* Сначала создаем путь. Просто описатель пути. */

CGMutablePathRef path = CGPathCreateMutable();

/* Это границы прямоугольника. */

CGRect rectangle = CGRectMake(10.0f,

10.0f,

200.0f,

300.0f);

/* Добавляем прямоугольник к пути. */

CGPathAddRect(path,

NULL,

rectangle);

/* Получаем описатель текущего контекста. */

CGContextRef currentContext = UIGraphicsGetCurrentContext();

/* Масштабируем все фигуры, отрисованные в графическом контексте,

уменьшая их на половину. */

CGContextScaleCTM(currentContext,

0.5f,

0.5f);

/* Добавляем путь к контексту. */

CGContextAddPath(currentContext,

path);

/* Задаем голубой в качестве цвета заливки. */

[[UIColor colorWithRed:0.20f

green:0.60f

blue:0.80f

alpha:1.0f] setFill];

/* Задаем для обводки коричневый цвет. */

[[UIColor brownColor] setStroke];

/* Задаем для ширины (обводки) значение 5. */

CGContextSetLineWidth(currentContext,

5.0f);

/* Проводим путь в контексте и применяем к нему заливку. */

CGContextDrawPath(currentContext,

kCGPathFillStroke);

/* Избавляемся от пути. */

Страницы: «« ... 7071727374757677 »»

Читать бесплатно другие книги:

Рассмотрены основы информатики и описаны современные аппаратные средства персонального компьютера. С...
Молодые парни из экстремистской организации «Русский трибунал» объявили партизанскую войну «предател...
Покончив с несчастливым браком, Грейс решила, что больше никогда не доверится мужчине и не поставит ...
Лиз Сазерленд только мечтала о том, чтобы черная полоса ее жизни когда-нибудь сменилась белой. Пробл...
В старину ставили храмы на полях сражений в память о героях и мучениках, отдавших за Родину жизнь. Н...
В учебном пособии представлены вариативные авторские методики воспитания и развития волевых качеств ...