Градиенты

Кварц обеспечивает два непрозрачных типа данных для создания градиентов —CGShadingRef и CGGradientRef. Можно использовать или их для создания осевых или радиальных градиентов. Градиент является заливкой, варьирующейся от одного цвета до другого.

Осевой градиент (также названный линейным градиентом) варьируется вдоль оси между двумя определенными конечными точками. Все точки, лежащие на перпендикуляре строки к оси, имеют то же значение цвета.

Радиальный градиент является заливкой, варьирующейся радиально вдоль оси между двумя определенными концами, которые обычно являются оба кругами. Точки совместно используют то же значение цвета, если они лежат на окружности круга, центральная точка которого падает на ось. Радиус круговых разделов градиента определяется радиусами кругов конца; радиус каждого промежуточного круга варьируется линейно от одного конца до другого.

Эта глава обеспечивает примеры видов линейных и радиальных градиентов, которые можно создать с Кварцем, сравнивает два подхода, которые Вы можете проявить к рисованию градиентов, и затем показываете, как использовать каждый непрозрачный тип данных для создания градиента.

Примеры осевого и радиального градиента

Кварцевые функции обеспечивают богатый словарь для создания эффектов градиента. Этот раздел показывает некоторые результаты, которых можно достигнуть. Осевой градиент на рисунке 8-1 варьируется между одной конечной точкой, которая является оттенком оранжевого и другого, который является оттенком желтого. В этом случае ось под углом на 45 градусов относительно источника.

Рисунок 8-1  осевой градиент вдоль оси на 45 градусов
An axial gradient along a 45 degree axis

Кварц также позволяет Вам указать цвета и расположения вдоль оси для создания более сложных осевых градиентов, как показано на рисунке 8-2. Цвет в начальной точке является оттенком красного цвета, и цвет в конечной точке является оттенком фиолетового. Однако существует также пять расположений на оси, цвет которой выбран к оранжевому, желтому, зеленому, синему цвету, и цвета индиго, соответственно. Можно думать о результате как о шести последовательных линейных градиентах вдоль той же оси. Несмотря на то, что ось, используемая здесь, совпадает с, который использовал на рисунке 8-1 (угол на 45 градусов), это не должно быть. Угол оси определяется начальной и конечной точкой, которую Вы обеспечиваете.

Рисунок 8-2  осевой градиент, создаваемый с семью расположениями и цветами
An axial gradient created with seven locations and colors

Рисунок 8-3 показывает радиальный градиент, варьирующийся между маленьким, ярким красным кругом и большим черным.

Рисунок 8-3  радиальный градиент, варьирующийся между двумя кругами
A radial gradient that varies between two circles

С Кварцем Вы не ограничиваетесь созданием градиентов на основе цветных изменений; можно варьироваться только альфа, или можно варьироваться альфа вместе с другими компонентами цвета. Рисунок 8-4 показывает градиент, красные, зеленые, и синие компоненты которого остаются постоянными, поскольку альфа-значение варьируется от 1,0 до 0,1.

Рисунок 8-4  радиальный градиент, создаваемый путем варьирования только альфа-компонента
A radial gradient created by varying only the alpha component

Можно расположить круги в радиальный градиент для создания множества форм. Если один круг частично или полностью вне другого, Кварц создает коническую поверхность для кругов, имеющих неравные окружности и цилиндрическую поверхность для кругов, имеющих равные окружности. Общее использование радиального градиента должно создать теневую сферу, как показано на рисунке 8-5. В этом случае, единственная точка (круг с радиусом 0) находится в большем кругу.

Рисунок 8-5  радиальный градиент, варьирующийся между точкой и кругом
A radial gradient that varies between a point and a circle

Можно создать более сложные эффекты вложением несколько радиальных градиентов, подобных форме, показанной на рисунке 8-6. Тороидальная часть формы создается с помощью концентрических кругов.

Рисунок 8-6  Вложенные радиальные градиенты
Nested radial gradients

Сравнение CGShading и объектов CGGradient

С двумя типами объектов, доступных для создания градиентов, Вы могли бы задаваться вопросом, который является лучшим для использования. Этот раздел помогает ответить на тот вопрос.

CGShadingRef непрозрачный тип данных дает Вам контроль над тем, как вычислен цвет в каждой точке в градиенте. Прежде чем можно будет создать объект CGShading, необходимо создать объект CGFunction (CGFunctionRef) это определяет функцию для вычислений, раскрашивает градиент. Запись пользовательской функции дает Вам свободу создать плавные градиенты, такие как показанные на рисунке 8-1, рисунке 8-3 и рисунке 8-5 или больше нетрадиционные эффекты, такие как показанный на рисунке 8-12.

При создании объекта CGShading Вы указываете, является ли это осевым (линейный) или радиальный. Вместе с функцией вычисления градиента (инкапсулировавший как объект CGFunction) Вы также предоставляете цветовое пространство, и начальные и конечные точки или радиусы, в зависимости от того, рисуете ли Вы осевой или радиальный градиент. В рисовании времени Вы просто передаете объект CGShading вместе с контекстом получения к функции CGContextDrawShading. Кварц вызывает Вашу функцию вычисления градиента для каждой точки в градиенте.

Объект CGGradient является подмножеством объекта CGShading, это разработано с простотой в употреблении в памяти. CGGradientRef непрозрачный тип данных является прямым для использования, потому что Кварц вычисляет цвет в каждой точке в градиенте для Вас — Вы не предоставляете функцию вычисления градиента. При создании объекта градиента Вы обеспечиваете массив расположений и цветов. Кварц вычисляет градиент для каждого набора непрерывных расположений, с помощью цвета, который Вы присваиваете каждому расположению как конечные точки для градиента. Можно установить объект градиента использовать единственный запуск и конечное расположение, как показано на рисунке 8-1, или можно обеспечить ряд вопросов для создания эффекта, подобного тому, что показано на рисунке 8-2. Возможность обеспечить больше чем два расположения является преимуществом перед использованием объекта CGShading, ограничивающегося двумя расположениями.

При создании объекта CGGradient Вы просто устанавливаете цветовое пространство, расположения и цвет для каждого расположения. Когда Вы рисуете к контексту с помощью объекта градиента, Вы указываете, должен ли Кварц нарисовать осевой или радиальный градиент. В рисовании времени Вы указываете начальные и конечные точки или радиусы, в зависимости от того, рисуете ли Вы осевой или радиальный градиент, в отличие от объектов CGShading, геометрия которых определяется во время создания, не в рисовании времени.

Таблица 8-1 суммирует различия между двумя непрозрачными типами данных.

Табличные 8-1  Различия между CGShading и объектами CGGradient

CGGradient

CGShading

Может использовать тот же объект нарисовать осевые и радиальные градиенты.

Потребность создать отдельные объекты для осевых и радиальных градиентов.

Установите геометрию градиента в рисовании времени.

Установите геометрию градиента во время создания объекта.

Кварц вычисляет цвета для каждой точки в градиенте.

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

Простой определить больше чем два расположения и цвета.

Должен разработать Ваш обратный вызов для использования больше чем двух расположений и цветов, таким образом, требуется немного больше работы с Вашей стороны.

Расширение цвета вне конца градиента

При создании градиента у Вас есть опция заполнения пространства вне концов градиента со сплошным цветом. Кварц использует цвет, определенный на границе градиента как цвет заливки. Можно расшириться вне запуска градиента, конца градиента или обоих. Можно применить опцию к осевому, или радиальный градиент создал использование или объект CGShading или объект CGGradient. Каждый тип объектных констант предоставлений, которые можно использовать для установки дополнительной опции, как Вы будете видеть в Использовании Объекта CGGradient и Используя Объект CGShading.

Рисунок 8-7 показывает осевой градиент, расширяющийся и при запуске и при конечных расположениях. Строка в числе показывает ось градиента. Как Вы видите, цвета заливки соответствуют цветам в начальных и конечных точках.

Рисунок 8-7  , Расширяющий осевой градиент
Extending an axial gradient

Рисунок 8-8 сравнивает радиальный градиент, не использующий дополнительные опции с той, использующей дополнительные опции и для запуска и для конечных расположений. Кварц принимает значения начального и конечного цвета и использует те сплошные цвета для расширения поверхности как показано. Данные показывают запуск и конечные круги и ось градиента.

Рисунок 8-8  , Расширяющий радиальный градиент
Extending a radial gradient

Используя объект CGGradient

Объект CGGradient является абстрактным определением градиента — он просто указывает цвета и расположения, но не геометрию. Можно использовать этот тот же объект и для осевых и для радиальных конфигураций. Как абстрактное определение, объекты CGGradient являются, возможно, с большей готовностью допускающими повторное использование, чем их дубликаты, объекты CGShading. Не привязывая геометрию объект CGGradient позволяет возможность итеративного рисования градиентов на основе той же цветовой схемы без потребности в том, чтобы также связывать ресурсы памяти в многократных объектах CGGradient.

Поскольку Кварц вычисляет градиент для Вас, использование объекта CGGradient создать и нарисовать градиент является довольно прямым, требуя этих шагов:

  1. Создайте объект CGGradient, предоставив цветовое пространство, массив двух или больше компонентов цвета, массив двух или больше расположений и число элементов в каждом из двух массивов.

  2. Нарисуйте градиент путем вызова также CGContextDrawLinearGradient или CGContextDrawRadialGradient и предоставление контекста, объекта CGGradient, таща опции, и утверждение и конечную геометрию (указывает для осевых градиентов или центров круга и радиусов для радиальных градиентов).

  3. Выпустите объект CGGradient, когда Вам больше не будет нужен он.

Расположение является a CGFloat значение в диапазоне 0,0 к 1,0, включительно, который указывает нормализованное расстояние вдоль оси градиента. В то время как 1.0 указывает конечную точку оси, значение 0,0 указывает начальную точку оси. Другие значения указывают пропорцию расстояния, такой как 0,25 для одной четверти расстояния от начальной точки и 0.5 для средней точки на оси. Как минимум Кварц использует два расположения. Если Вы передаете NULL для массива расположений Кварц использует 0 для первого расположения и 1 для второго.

Число компонентов цвета на цвет зависит от цветового пространства. Для экранного получения Вы используете цветовое пространство RGB. Поскольку Кварц рисует с альфой, каждый экранный цвет имеет четыре компонента — красный, зеленый, синий, и альфа. Так, для экранного получения число элементов в массиве компонента цвета, который Вы обеспечиваете, должно содержать четыре раза число расположений. Кварц компоненты цвета RGBA может варьироваться по значению от 0,0 до 1,0, включительно.

Перечисление 8-1 является фрагментом кода, создающим объект CGGradient. После объявления необходимых переменных, кодовые наборы расположения и необходимое число компонентов цвета (для этого примера, 2 X 4 = 8). Это создает универсальное цветовое пространство RGB. (В iOS, где универсальные цветовые пространства RGB не доступны, Ваш код должен вызвать CGColorSpaceCreateDeviceRGB вместо этого.) Затем это передает необходимые параметры функции CGGradientCreateWithColorComponents. Можно также использовать функцию CGGradientCreateWithColors если Ваше приложение устанавливает объекты CGColor, который удобен.

Перечисление 8-1  , Создающее объект CGGradient

CGGradientRef myGradient;
CGColorSpaceRef myColorspace;
size_t num_locations = 2;
CGFloat locations[2] = { 0.0, 1.0 };
CGFloat components[8] = { 1.0, 0.5, 0.4, 1.0,  // Start color
                          0.8, 0.8, 0.3, 1.0 }; // End color
 
myColorspace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
myGradient = CGGradientCreateWithColorComponents (myColorspace, components,
                          locations, num_locations);

После создания объекта CGGradient можно использовать его для рисования осевого или линейного градиента. Перечисление 8-2 является фрагментом кода, объявляющим и устанавливающим начальные и конечные точки для линейного градиента и затем красящим градиент. Рисунок 8-1 показывает результат. Код не показывает, как получить объект CGContext (myContext).

Перечисление 8-2  Крася осевой градиент с помощью объекта CGGradient

CGPoint myStartPoint, myEndPoint;
myStartPoint.x = 0.0;
myStartPoint.y = 0.0;
myEndPoint.x = 1.0;
myEndPoint.y = 1.0;
CGContextDrawLinearGradient (myContext, myGradient, myStartPoint, myEndPoint, 0);

Перечисление 8-3 является фрагментом кода, использующим объект CGGradient, создаваемый в Перечислении 8-1 для рисования радиального градиента показанным на рисунке 8-9. Этот пример иллюстрирует результат расширения области градиента путем заполнения его сплошным цветом.

Перечисление 8-3  Крася радиальный градиент с помощью объекта CGGradient

CGPoint myStartPoint, myEndPoint;
CGFloat myStartRadius, myEndRadius;
myStartPoint.x = 0.15;
myStartPoint.y = 0.15;
myEndPoint.x = 0.5;
myEndPoint.y = 0.5;
myStartRadius = 0.1;
myEndRadius = 0.25;
CGContextDrawRadialGradient (myContext, myGradient, myStartPoint,
                         myStartRadius, myEndPoint, myEndRadius,
                         kCGGradientDrawsAfterEndLocation);
Рисунок 8-9  радиальный градиент нарисовал использование объекта CGGradient
A radial gradient painted using a CGGradient object

Радиальный градиент, показанный на рисунке 8-4, создавался с помощью переменных, показанных в Перечислении 8-4.

Перечисление 8-4  переменные раньше создавало радиальный градиент переменной альфой

CGPoint myStartPoint, myEndPoint;
CGFloat myStartRadius, myEndRadius;
myStartPoint.x = 0.2;
myStartPoint.y = 0.5;
myEndPoint.x = 0.65;
myEndPoint.y = 0.5;
myStartRadius = 0.1;
myEndRadius = 0.25;
size_t num_locations = 2;
CGFloat locations[2] = { 0, 1.0 };
CGFloat components[8] = { 0.95, 0.3, 0.4, 1.0,
                          0.95, 0.3, 0.4, 0.1 };

Перечисление 8-5 показывает, что переменные раньше создавали серый градиент, показанный на рисунке 8-10, имеющем три расположения.

Перечисление 8-5  переменные раньше создавало серый градиент

size_t num_locations = 3;
CGFloat locations[3] = { 0.0, 0.5, 1.0};
CGFloat components[12] = {  1.0, 1.0, 1.0, 1.0,
                            0.5, 0.5, 0.5, 1.0,
                            1.0, 1.0, 1.0, 1.0 };
Рисунок 8-10  осевой градиент с тремя расположениями
An axial gradient with three locations

Используя объект CGShading

Вы устанавливаете градиент путем создания объекта CGShading вызывание функции CGShadingCreateAxial или CGShadingCreateRadial, предоставление следующих параметров:

CGFunction возражают, что Вы предоставляете к функциям создания CGShading, содержит структуру обратных вызовов, и весь информационный Кварц должен реализовать Ваш обратный вызов. Возможно, самая хитрая часть установки объекта CGShading создает объект CGFunction. Когда Вы вызываете функцию CGFunctionCreate, Вы предоставляете следующее:

Если необходимо сделать так, после создания объекта CGShading можно установить дополнительное отсечение. Затем вызовите функцию CGContextDrawShading нарисовать область отсечения контекста с градиентом. Когда Вы вызываете эту функцию, Кварц вызывает Ваш обратный вызов для получения значений цвета, охватывающих диапазон от начальной точки до конечной точки.

Когда Вам больше не нужен объект CGShading, Вы выпускаете его путем вызывания функции CGShadingRelease.

Рисование Осевого Градиента Используя Объект CGShading и Рисование Радиального градиента Используя Объект CGShading обеспечивают поэтапные инструкции при записи кода, использующего объект CGShading нарисовать градиент.

Рисование осевого градиента Используя объект CGShading

Осевые и радиальные градиенты требуют, чтобы Вы выполнили подобные шаги. Этот пример показывает, как нарисовать осевой градиент с помощью объекта CGShading, создать полукруглую траекторию отсечения в графическом контексте, затем нарисуйте градиент к отсеченному контексту для достижения вывода, показанного на рисунке 8-11.

Рисунок 8-11  осевой градиент, отсекающийся и красящийся
An axial gradient that is clipped and painted

Для рисования осевого градиента показанным в числе выполните шаги, объясненные в этих разделах:

  1. Установите объект CGFunction вычислить значения цвета

  2. Создайте объект CGShading для осевого градиента

  3. Отсеките контекст

  4. Нарисуйте осевой градиент Используя объект CGShading

  5. Объекты выпуска

Установите объект CGFunction вычислить значения цвета

Можно вычислить значения цвета любым путем, Вам нравится, пока Ваша цветная функция вычисления берет три параметра:

  • void *info. Это NULL или указатель на данные Вы передаете функции создания CGShading.

  • const CGFloat *in. Кварц передает in выстройте к своему обратному вызову. Значения в массиве должны быть в диапазоне входного значения, определенном для Вашего объекта CGFunction. Для этого примера входной диапазон от 0 до 1; см. Перечисление 8-7.

  • CGFloat *out. Ваш обратный вызов передает out выстройте к Кварцу. Это содержит один элемент для каждого компонента цвета в цветовом пространстве и альфа-значение. Выходные значения должны быть в диапазоне выходного значения, определенном для Вашего объекта CGFunction. Для этого примера выходной диапазон от 0 до 1; см. Перечисление 8-7.

Для получения дополнительной информации об этих параметрах посмотрите CGFunctionEvaluateCallback.

Перечисление 8-6 показывает функцию, вычисляющую значения компонента цвета путем умножения значений, определенных в постоянном массиве входным значением. Поскольку входное значение колеблется от 0 до 1, диапазон выходных значений от черного цвета (для RGB, значения 0, 0, 0), через (1, 0.5), который является фиолетовым оттенком. Обратите внимание на то, что последний компонент всегда устанавливается в 1, так, чтобы цвета были всегда полностью непрозрачны.

Перечисление 8-6  Вычисляя значения компонента цвета

 
static void myCalculateShadingValues (void *info,
                            const CGFloat *in,
                            CGFloat *out)
{
    CGFloat v;
    size_t k, components;
    static const CGFloat c[] = {1, 0, .5, 0 };
 
    components = (size_t)info;
 
    v = *in;
    for (k = 0; k < components -1; k++)
        *out++ = c[k] * v;
     *out++ = 1;
}
 

После записи обратного вызова для вычислений значений цвета, Вы упаковываете его как часть объекта CGFunction. Это - объект CGFunction, который Вы предоставляете к Кварцу при создании объекта CGShading. Перечисление 8-7 показывает функцию, создающую объект CGFunction, содержащий обратный вызов от Перечисления 8-6. Подробное объяснение каждой пронумерованной строки кода появляется после перечисления.

Перечисление 8-7  , Создающее объект CGFunction

 
static CGFunctionRef myGetFunction (CGColorSpaceRef colorspace)// 1
{
    size_t numComponents;
    static const CGFloat input_value_range [2] = { 0, 1 };
    static const CGFloat output_value_ranges [8] = { 0, 1, 0, 1, 0, 1, 0, 1 };
    static const CGFunctionCallbacks callbacks = { 0,// 2
                                &myCalculateShadingValues,
                                NULL };
 
    numComponents = 1 + CGColorSpaceGetNumberOfComponents (colorspace);// 3
    return CGFunctionCreate ((void *) numComponents, // 4
                                1, // 5
                                input_value_range, // 6
                                numComponents, // 7
                                output_value_ranges, // 8
                                &callbacks);// 9
}

Вот то, что делает код:

  1. Занимает цветовое место в качестве параметра.

  2. Объявляет структуру обратных вызовов и заполняет его версией структуры (0), указатель на Ваш обратный вызов вычисления компонента цвета, и NULL для дополнительной функции выпуска.

  3. Вычисляет число компонентов цвета в цветовом пространстве и постепенно увеличивает значение 1 для учета альфа-значения.

  4. Передает указатель на numComponents значение. Это значение используется обратным вызовом myCalculateShadingValues определить число компонентов для вычислений.

  5. Указывает, что 1 число входных значений к обратному вызову.

  6. Обеспечивает массив, указывающий допустимые интервалы для ввода. Этот массив содержит 0 и 1.

  7. Передает число выходных значений, которое является числом компонентов цвета плюс альфа.

  8. Обеспечивает массив, указывающий допустимые интервалы для каждого выходного значения. Этот массив указывает, для каждого компонента, интервалы 0 и 1. Поскольку существует четыре компонента, в этом массиве существует восемь элементов.

  9. Передает указатель на структуру обратного вызова, объявленную и заполненную ранее.

Создайте объект CGShading для осевого градиента

Для создания объекта CGShading Вы вызываете функцию CGShadingCreateAxial, как показано в Перечислении 8-8, передавая цветовое пространство, начальные и конечные точки, объект CGFunction и булево значение, указывающее, заполнить ли область вне начальных и конечных точек градиента.

Перечисление 8-8  , Создающее CGShading, возражает для осевого градиента

CGPoint     startPoint,
            endPoint;
CGFunctionRef myFunctionObject;
CGShadingRef myShading;
 
startPoint = CGPointMake(0,0.5);
endPoint = CGPointMake(1,0.5);
colorspace = CGColorSpaceCreateDeviceRGB();
myFunctionObject = myGetFunction (colorspace);
 
myShading = CGShadingCreateAxial (colorspace,
                        startPoint, endPoint,
                        myFunctionObject,
                        false, false);

Отсеките контекст

При рисовании градиента Кварц заполняет текущий контекст. Рисование градиента отличается от работы с цветами и образцами, использующимися, чтобы перечеркнуть и заполнить объекты контуров. В результате, если Вы хотите, чтобы Ваш градиент появился в определенной форме, необходимо отсечь контекст соответственно. Код в Перечислении 8-9 добавляет полукруг к текущему контексту так, чтобы градиент был нарисован в ту отсекаемую область, как показано на рисунке 8-11.

Если Вы посмотрите тщательно, то Вы заметите, что код должен привести к половине круга, тогда как данные показывают половину эллипса. Почему? Вы будете видеть при рассмотрении всей подпрограммы в Полной Подпрограмме для Осевого Градиента Используя Объект CGShading что также масштабируется контекст. Больше об этом позже. Несмотря на то, что Вы, возможно, не должны были бы применять масштабирование или клип в Вашем приложении, они и много других опций существуют в Кварце, 2D, чтобы помочь Вам достигнуть интересных эффектов.

Перечисление 8-9  , Добавляющее полукруг, отсекает к графическому контексту

    CGContextBeginPath (myContext);
    CGContextAddArc (myContext, .5, .5, .3, 0,
                    my_convert_to_radians (180), 0);
    CGContextClosePath (myContext);
    CGContextClip (myContext);

Нарисуйте осевой градиент Используя объект CGShading

Вызовите функцию CGContextDrawShading заполнить текущий контекст с помощью цветового градиента, указанного в объекте CGShading:

CGContextDrawShading (myContext, myShading);

Объекты выпуска

Вы вызываете функцию CGShadingRelease когда Вам больше не нужен объект CGShading. Также необходимо выпустить объект CGColorSpace и объект CGFunction как показано в Перечислении 8-10.

Перечисление 8-10  , Выпускающее объекты

CGShadingRelease (myShading);
CGColorSpaceRelease (colorspace);
CGFunctionRelease (myFunctionObject);

Полная подпрограмма для осевого градиента Используя объект CGShading

Код в Перечислении 8-11 показывает полную подпрограмму, красящую осевой градиент, израсходовав набор объекта CGFunction в Перечислении 8-7 и обратном вызове, показанном в Перечислении 8-6. Подробное объяснение каждой пронумерованной строки кода появляется после перечисления.

Перечисление 8-11  Крася осевой градиент с помощью объекта CGShading

void myPaintAxialShading (CGContextRef myContext,// 1
                            CGRect bounds)
{
    CGPoint     startPoint,
                endPoint;
    CGAffineTransform myTransform;
    CGFloat width = bounds.size.width;
    CGFloat height = bounds.size.height;
 
 
    startPoint = CGPointMake(0,0.5); // 2
    endPoint = CGPointMake(1,0.5);// 3
 
    colorspace = CGColorSpaceCreateDeviceRGB();// 4
    myShadingFunction = myGetFunction(colorspace);// 5
 
    shading = CGShadingCreateAxial (colorspace, // 6
                                 startPoint, endPoint,
                                 myShadingFunction,
                                 false, false);
 
    myTransform = CGAffineTransformMakeScale (width, height);// 7
    CGContextConcatCTM (myContext, myTransform);// 8
    CGContextSaveGState (myContext);// 9
 
    CGContextClipToRect (myContext, CGRectMake(0, 0, 1, 1));// 10
    CGContextSetRGBFillColor (myContext, 1, 1, 1, 1);
    CGContextFillRect (myContext, CGRectMake(0, 0, 1, 1));
 
    CGContextBeginPath (myContext);// 11
    CGContextAddArc (myContext, .5, .5, .3, 0,
                        my_convert_to_radians (180), 0);
    CGContextClosePath (myContext);
    CGContextClip (myContext);
 
    CGContextDrawShading (myContext, shading);// 12
    CGColorSpaceRelease (colorspace);// 13
    CGShadingRelease (shading);
    CGFunctionRelease (myShadingFunction);
 
    CGContextRestoreGState (myContext); // 14
}

Вот то, что делает код:

  1. Берет в качестве параметров графический контекст и прямоугольник для вовлечения.

  2. Присваивает значение начальной точке. Подпрограмма вычисляет значения на основе пространства пользователя, варьирующегося от 0 до 1. Вы будете масштабировать пространство позже для окна, которое вовлекает Кварц. Можно думать об этом координатном расположении как x в крайне левой стороне и y в 50% от нижней части.

  3. Присваивает значение конечной точке. Можно думать об этом координатном расположении как x в далекой правой стороне и y в 50% от нижней части. Как Вы видите, ось для градиента является горизонтальной строкой.

  4. Создает цветовое пространство для устройства RGB, потому что эта подпрограмма рисует к дисплею.

  5. Создает объект CGFunction путем вызова подпрограммы, показанной в Перечислении 8-7 и передачи цветового пространства, которое Вы просто создали.

  6. Создает объект CGShading для осевого градиента. Последние два параметра false, сигнализировать, что Кварц не должен заполнять область вне начальных и конечных точек.

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

  8. Связывает преобразование, которое Вы просто устанавливаете с графическим контекстом, переданным подпрограмме.

  9. Сохраняет состояние графики, чтобы позволить Вам восстановить это состояние позже.

  10. Устанавливает область отсечения. Эта строка и следующие две строки отсекают контекст к прямоугольнику, который заполнен белым. Эффект состоит в том, что градиент нарисован к окну с белым фоном.

  11. Создает путь. Эта строка и следующие три строки устанавливают дугу, которая является половиной круга и добавляет его к графическому контексту как область отсечения. Эффект состоит в том, что градиент нарисован к области, которая является половиной круга. Однако круг будет преобразован высотой и шириной окна (см. шаг 8), приводя к заключительному эффекту градиента, нарисованного к половине эллипса. Поскольку окно изменено пользователем, область отсечения изменена.

  12. Красит градиент к графическому контексту, преобразовывая и отсекая градиент, как описано ранее.

  13. Объекты выпусков. Эта строка и следующие две строки выпускают все объекты, которые Вы создали.

  14. Восстанавливает состояние графики к состоянию, существовавшему перед установкой заполненного фона и отсеченный к половине круга. Восстановленное состояние все еще преобразовывается шириной и высотой окна.

Рисование радиального градиента Используя объект CGShading

Этот пример показывает, как использовать объект CGShading произвести вывод, показанный на рисунке 8-12.

Рисунок 8-12  радиальный градиент создал использование объекта CGShading
A radial gradient creating using a CGShading object

Для рисования радиального градиента выполните шаги, объясненные в следующих разделах:

  1. Установите объект CGFunction вычислить значения цвета.

  2. Создайте объект CGShading для радиального градиента

  3. Нарисуйте радиальный градиент Используя объект CGShading

  4. Объекты выпуска

Установите объект CGFunction вычислить значения цвета

Нет никакого различия между записью функций для вычислений значений цвета для радиальных и осевых градиентов. Фактически, можно следовать инструкциям, обрисованным в общих чертах для осевых градиентов в Установленном Объект CGFunction Вычислить Значения цвета. Перечисление 8-12 вычисляет цвет так, чтобы компоненты цвета варьировались синусоидально с периодом на основе значений частоты, объявленных в функции. Результат, замеченный на рисунке 8-12, очень отличается от цветов, показанных на рисунке 8-11. Несмотря на различия в цвете вывод, код в Перечислении 8-12 подобен Перечислению 8-6, в котором каждая функция следует за тем же прототипом. Каждая функция берет одно входное значение и вычисляет значения N, один для каждого компонента цвета цветового пространства плюс альфа-значение.

Перечисление 8-12  Вычисляя значения компонента цвета

static void  myCalculateShadingValues (void *info,
                                const CGFloat *in,
                                CGFloat *out)
{
    size_t k, components;
    double frequency[4] = { 55, 220, 110, 0 };
    components = (size_t)info;
    for (k = 0; k < components - 1; k++)
        *out++ = (1 + sin(*in * frequency[k]))/2;
     *out++ = 1; // alpha
}

Вспомните, что после записи цветной функции вычисления необходимо создать объект CGFunction, как описано для осевых значений в Установленном Объект CGFunction Вычислить Значения цвета.

Создайте объект CGShading для радиального градиента

Для создания CGShading возражают или радиальный градиент, Вы вызываете функцию CGShadingCreateRadial, как показано в Перечислении 8-13, передавая цветовое пространство, начальные и конечные точки, запускаясь и конечные радиусы, объект CGFunction и булевы значения, чтобы указать, заполнить ли область вне начальных и конечных точек градиента.

Перечисление 8-13  , Создающее CGShading, возражает для радиального градиента

    CGPoint startPoint, endPoint;
    CGFloat startRadius, endRadius;
 
    startPoint = CGPointMake(0.25,0.3);
    startRadius = .1;
    endPoint = CGPointMake(.7,0.7);
    endRadius = .25;
    colorspace = CGColorSpaceCreateDeviceRGB();
    myShadingFunction = myGetFunction (colorspace);
    CGShadingCreateRadial (colorspace,
                    startPoint,
                    startRadius,
                    endPoint,
                    endRadius,
                    myShadingFunction,
                    false,
                    false);

Нарисуйте радиальный градиент Используя объект CGShading

Вызывание функции CGContextDrawShading заполняет текущий контекст с помощью указанного цветового градиента, указанного в объекте CGShading.

CGContextDrawShading (myContext, shading);

Заметьте использование той же функции для рисования градиента независимо от того, является ли градиент осевым или радиальным.

Объекты выпуска

Вы вызываете функцию CGShadingRelease когда Вам больше не нужен объект CGShading. Также необходимо выпустить объект CGColorSpace и объект CGFunction как показано в Перечислении 8-14.

  Код перечисления 8-14, выпускающий объекты

CGShadingRelease (myShading);
CGColorSpaceRelease (colorspace);
CGFunctionRelease (myFunctionObject);

Полная подпрограмма для рисования радиального градиента Используя объект CGShading

Код в Перечислении 8-15 показывает полную подпрограмму, красящую радиальный градиент, израсходовав набор объекта CGFunction в Перечислении 8-7 и обратном вызове, показанном в Перечислении 8-12. Подробное объяснение каждой пронумерованной строки кода появляется после перечисления.

Перечисление 8-15  подпрограмма, красящая радиальный градиент с помощью объекта CGShading

void myPaintRadialShading (CGContextRef myContext,// 1
                            CGRect bounds);
{
    CGPoint startPoint,
            endPoint;
    CGFloat startRadius,
            endRadius;
    CGAffineTransform myTransform;
    CGFloat width = bounds.size.width;
    CGFloat height = bounds.size.height;
 
    startPoint = CGPointMake(0.25,0.3); // 2
    startRadius = .1;  // 3
    endPoint = CGPointMake(.7,0.7); // 4
    endRadius = .25; // 5
 
    colorspace = CGColorSpaceCreateDeviceRGB(); // 6
    myShadingFunction = myGetFunction (colorspace); // 7
 
    shading = CGShadingCreateRadial (colorspace, // 8
                            startPoint, startRadius,
                            endPoint, endRadius,
                            myShadingFunction,
                            false, false);
 
    myTransform = CGAffineTransformMakeScale (width, height); // 9
    CGContextConcatCTM (myContext, myTransform); // 10
    CGContextSaveGState (myContext); // 11
 
    CGContextClipToRect (myContext, CGRectMake(0, 0, 1, 1)); // 12
    CGContextSetRGBFillColor (myContext, 1, 1, 1, 1);
    CGContextFillRect (myContext, CGRectMake(0, 0, 1, 1));
 
    CGContextDrawShading (myContext, shading); // 13
    CGColorSpaceRelease (colorspace); // 14
    CGShadingRelease (shading);
    CGFunctionRelease (myShadingFunction);
 
    CGContextRestoreGState (myContext); // 15
}

Вот то, что делает код:

  1. Берет в качестве параметров графический контекст и прямоугольник для вовлечения.

  2. Присваивает значение центру стартового круга. Подпрограмма вычисляет значения на основе пространства пользователя, варьирующегося от 0 до 1. Вы масштабируетесь, пространство позже для окна Quartz вовлекает. Можно думать об этом координатном расположении как x в 25% слева и y в 30% от нижней части.

  3. Присваивает радиус стартового круга. Можно думать об этом как о 10% ширины пространства пользователя.

  4. Присваивает значение центру конечного круга. Можно думать об этом координатном расположении как x в 70% слева и y в 70% от нижней части.

  5. Присваивает радиус конечного круга. Можно думать об этом как о 25% ширины пространства пользователя. Конечный круг будет больше, чем стартовый круг. Коническая форма будет ориентирована слева направо, снабжена подсказкой вверх.

  6. Создает цветовое пространство для устройства RGB, потому что эта подпрограмма рисует к дисплею.

  7. Создает CGFunctionObject путем вызова подпрограммы, показанной в Перечислении 8-7 и передачи цветового пространства, которое Вы просто создали. Однако вспомните использование цветной функции вычисления, показанной в Перечислении 8-12.

  8. Создает объект CGShading для радиального градиента. Последние два параметра false, сигнализировать, что Кварц не должен заполнять область вне начальных и конечных точек градиента.

  9. Устанавливает аффинное преобразование, масштабирующееся к высоте и ширине окна, используемого для рисования. Обратите внимание на то, что высота не обязательно равна ширине. Фактически, трансформация изменится каждый раз, когда пользователь изменяет размеры окна.

  10. Связывает преобразование, которое Вы просто устанавливаете с графическим контекстом, переданным подпрограмме.

  11. Сохраняет состояние графики, чтобы позволить Вам восстановить это состояние позже.

  12. Устанавливает область отсечения. Эта строка и следующие две строки отсекают контекст к прямоугольнику, который заполнен белым. Эффект состоит в том, что градиент нарисован к окну с белым фоном.

  13. Красит градиент к графическому контексту, преобразовывающему градиент, как описано ранее.

  14. Объект выпусков. Эта строка и следующие две строки выпускают все объекты, которые Вы создали.

  15. Восстанавливает состояние графики к состоянию, существовавшему перед установкой заполненного фона. Восстановленное состояние все еще преобразовывается шириной и высотой окна.

См. также