В этой серии статей я обсуждаю создание диаграмм и графиков, используя не что иное, как Quartz 2D, API рендеринга графики, созданный Apple, который является частью Core Graphics. Возможно, вы захотите освоиться с частями 1 , 2 , 3 и 4 .
Рисование текста
Наконец, мы собираемся написать текст на графике. Вы можете быть удивлены, почему я так долго откладывал такую простую задачу. На самом деле, не нужно много усилий, чтобы нарисовать строку в Quartz 2D. Давайте попробуем это: в GraphView, в конце drawRect
// Drawing text
CGContextSelectFont(context, "Helvetica", 44, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextSetFillColorWithColor(context, [[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0] CGColor]);
NSString *theText = @"Hi there!";
CGContextShowTextAtPoint(context, 100, 100, [theText cStringUsingEncoding:NSUTF8StringEncoding], [theText length]);
Здесь нет ничего сложного: мы выбираем шрифт, цвет, режим рисования, а затем рисуем случайную строку где-то внутри графика. Как вы думаете, результат будет выглядеть? Посмотрим:
К сожалению! Не совсем то, что мы хотели: текст нарисован с ног на голову. Это потому, что в системе координат, используемой в iOS, вертикальная координата идет сверху вниз. В основном все нарисовано с ног на голову. Возможно, вы уже заметили это, если пытались использовать более или менее сложный графический фон.
Мы можем помнить об этой особенности при рисовании графика и соответствующим образом корректировать логику. Мы могли бы использовать другой фон в конце концов, но когда дело доходит до рисования текста, мы должны столкнуться с проблемой.
К счастью, решение не сложно. Все, что нам нужно сделать, это преобразовать систему координат таким образом, чтобы вертикальная ось начиналась в нижней части графика и шла вверх — и есть несколько функций, которые позволяют нам делать именно это. Фактически, мы можем решить нашу проблему с помощью одной строки кода. Вставьте его до того, как закончится рисование любого текста:
CGContextSetTextMatrix (context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
Запустите приложение, и на этот раз текст должен выглядеть хорошо:
Давайте попробуем понять заклинание, которое спасло день. Вся магия заключается в шести параметрах, и здесь я упомяну только ненулевые. Вы можете прочитать подробное объяснение логики в документации для CGAffineTransform .
Итак, мы меняем используемую систему координат, верно? Шесть параметров описывают отношения между старой системой и новой системой. Самый первый параметр описывает отношение между координатой x
x
Здесь мы не хотим никаких изменений, поэтому значение параметра равно 1. Четвертый параметр описывает отношение между координатой y
y
Нам нужно только поменять направление, поэтому значение равно –1.
Как видите, в данном конкретном случае все очень просто. Однако вы можете определять более сложные преобразования, сжимать и сдвигать координаты по своему усмотрению. А пока давайте лучше рассмотрим другое полезное преобразование. Вот код:
CGContextSetTextMatrix(context, CGAffineTransformRotate(CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0), M_PI / 2));
Можете ли вы угадать, что он делает? Замените предыдущее волшебное заклинание этим, и вуаля:
Ну, мне пришлось изменить третий параметр CGContextShowTextAtPoint на 200, чтобы убедиться, что текст остается в границах графика. Видите, мы можем рисовать текст вертикально — это может быть очень полезно для рисования меток.
Чтобы подвести итог, давайте сделаем что-то по-настоящему, нумеруем точки данных линейного графика. Вот код, он не должен вас удивлять:
CGContextSetTextMatrix(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0.0, 0.0));
CGContextSelectFont(context, "Helvetica", 18, kCGEncodingMacRoman);
CGContextSetTextDrawingMode(context, kCGTextFill);
CGContextSetFillColorWithColor(context, [[UIColor colorWithRed:0 green:0 blue:0 alpha:1.0] CGColor]);
for (int i = 1; i < sizeof(data); i++)
{
NSString *theText = [NSString stringWithFormat:@"%d", i];
CGContextShowTextAtPoint(context, kOffsetX + i * kStepX, kGraphBottom - 5, [theText cStringUsingEncoding:NSUTF8StringEncoding], [theText length]);
}
И вот результат:
Выглядит хорошо, но было бы намного лучше, если бы метки были сосредоточены под точками данных, как вы думаете? Чтобы достичь этого, нам нужно знать ширину рисуемой метки, а затем внести поправку в ее координату x на половину ширины метки.
Вот строка кода, которая даст нам размер метки. Очевидно, нам нужно указать тот же шрифт, который используется для рисования текста:
CGSize labelSize = [theText sizeWithFont:[UIFont fontWithName:@"Helvetica" size:18]];
Наконец, это исправленная строка для фактического рисования метки:
CGContextShowTextAtPoint(context, kOffsetX + i * kStepX - labelSize.width/2, kGraphBottom - 5, [theText cStringUsingEncoding:NSUTF8StringEncoding], [theText length]);
Запустите приложение еще раз, и теперь метки будут хорошо выровнены под точками данных:
Как мы уже говорили в начале этой серии, работать с Quartz 2D не так сложно, вам просто нужно знать, как делать определенные вещи, и как только вы их освоите, вы сможете быстро двигаться вперед. Теперь вы можете делать все, что нужно для построения индивидуального графика любой сложности, используя Quartz 2D. Небо это предел!
Кварц 2D Индекс
Серия Александра Колесникова «Создание графика с использованием Quartz 2D» была разбита на 5 частей. Вы можете сослаться на серию, используя Quartz 2D Tag, и получить доступ к отдельным статьям, используя ссылки ниже.
- Создание графика с помощью Quartz 2D: часть 1
- Создание графика с помощью Quartz 2D: часть 2
- Создание графика с помощью Quartz 2D: часть 3
- Создание графика с помощью Quartz 2D: часть 4
- Создание графика с помощью Quartz 2D: часть 5