Разработка
Создаем гистограмму с помощью Swift Charts
На WWDC 22 Apple представила Swift Charts, фреймворк, позволяющий визуализировать данные в виде гистограмм. До его появления нам приходилось подключать всевозможные сторонние решения для построения графиков в SwiftUI. Визуализация данных с помощью аналогичного декларативного синтаксиса в SwiftUI — это просто фантастика.
Гистограмма — это всего лишь один из доступных вариантов визуализации данных. В целом, многие из методов, о которых вы сегодня узнаете, применимы и к другим графикам. Фактически, вы можете заменить всего один элемент, чтобы перейти от гистограммы к линейной диаграмме. Давайте погрузимся в работу!
Настройка данных диаграммы
Прежде чем приступить к созданию графика, важно иметь данные для работы. В этой статье я буду использовать данные о сборках, которые я использую в RocketSim:
/// Describes an Xcode build activity on a certain data, for a given duration. struct BuildActivity: Identifiable, Codable { var id: TimeInterval { date.timeIntervalSince1970 } let date: Date let scheme: String let numberOfBuilds: Int }
При запуске нового графика я рекомендую создать образец данных для работы. Вы можете использовать эти данные как в работающем приложении, так и в превью SwiftUI:
extension BuildActivity { static func sampleData() -> [BuildActivity] { [ sampleData(for: "RocketSim"), sampleData(for: "Stock Analyzer") ].flatMap { $0 } } private static func sampleData(for scheme: String) -> [BuildActivity] { (0...365).map { index -> BuildActivity in /// Create a random number of builds. Some days will not have any builds let numberOfBuilds = Int.random(in: 0...100) /// Using the index, we're creating a full year of data let date = Calendar.current.date(byAdding: .day, value: -index, to: .now)! return BuildActivity( date: date, scheme: scheme, numberOfBuilds: numberOfBuilds ) } } }
Эти статические методы позволяют создать коллекцию активностей сборок для двух разных схем. Этот набор данных отлично подходит для визуализации гистограммы в этой статье.
Создание базовой гистограммы
Мы можем использовать наши данные для создания базовой гистограммы с помощью Swift Charts в SwiftUI:
Код для этой диаграммы выглядит следующим образом:
import SwiftUI import Charts struct BarChart: View { let buildActivities: [BuildActivity] var body: some View { Chart(buildActivities) { buildActivity in BarMark( x: .value("Date", buildActivity.date, unit: .day), y: .value("Total Count", buildActivity.numberOfBuilds) ) } } }
После импорта фреймворка Charts мы можем использовать элемент Chart, передав ему данные нашей деятельности со сборками. Замыкание требует, чтобы мы вернули элемент данных, для которого мы получаем точку на графике. Вы можете видеть это как один столбик внутри нашей гистограммы.
Значения x и y определяют, как будут визуализированы данные. Мы установили единицу измерения даты в .day
, поскольку хотим показывать данные за каждый день. Вы можете изменить это значение, чтобы управлять временным периодом данных.
Управление диапазоном данных на диаграмме
Хотя базовая гистограмма и так выглядит отлично, она не очень удобна при отображении данных за целый год. Возможно, вам захочется увеличить масштаб данных за одну неделю. Это можно сделать двумя способами, каждый из которых дает разные результаты.
Первый способ — использовать модификатор chartXScale
:
/// Chart X scale zoom in, but data is visible out of bounds .chartXScale( domain: startDate...Date.now, range: .plotDimension(startPadding: 10, endPadding: 10) )
Настроив начальную дату на одну неделю назад, мы получим в результате следующий график:
Хотя мы можем четко видеть данные только за последние 7 дней, это не совсем удовлетворительный результат. Столбики выходят за границы, а наши метки шкалы y становятся перекрытыми. Вы все еще можете использовать этот подход в качестве функции масштабирования в сочетании с модификатором chartScrollableAxes
, но лучше настроить график только на те данные, которые вы хотите отобразить.
Другими словами, мы разделим наши данные так, чтобы они содержали данные только за семь дней:
BarChart(buildActivities: Array(BuildActivity.sampleData().prefix(7)))
Поскольку данные в нашем примере расположены в обратном порядке, мы можем использовать модификатор префикса, чтобы получить первые 7 элементов. Полученный график выглядит гораздо лучше:
Как изменить цвет гистограммы?
Цвет гистограммы по умолчанию будет соответствовать цвету accent вашего приложения. Вы можете изменить цвет с помощью модификатора foreground стиля:
Chart(buildActivities) { buildActivity in BarMark( x: .value("Date", buildActivity.date, unit: .day), y: .value("Total Count", buildActivity.numberOfBuilds) ) /// Change the color of bars to orange .foregroundStyle(Color.orange) }
Как разделить гистограмму на группы?
Гистограммы позволяют разбивать данные на группы и визуализировать их по отдельности. Например, мы можем разделить нашу гистограмму по заданной схеме:
Вам необходимо указать конкретное значение, которое будет использоваться для разделения данных. Рекомендуется использовать определенную категорию, которая не приведет к образованию слишком большого количества различных групп. Код для нашего примера выглядит следующим образом:
Chart(buildActivities) { buildActivity in BarMark( x: .value("Date", buildActivity.date, unit: .day), y: .value("Total Count", buildActivity.numberOfBuilds) ) /// Show a different color for each scheme .foregroundStyle( by: .value("Scheme", buildActivity.scheme) ) }
Swift Charts назначает цвет по умолчанию для каждой группы. Вы можете переопределить этот цвет, указав конкретный цвет для каждого идентификатора группы. В нашем случае мы указываем цвет для каждой заданной схемы:
Chart(buildActivities) { buildActivity in BarMark( x: .value("Date", buildActivity.date, unit: .day), y: .value("Total Count", buildActivity.numberOfBuilds) ) /// Show a different color for each scheme .foregroundStyle( by: .value("Scheme", buildActivity.scheme) ) } /// Customize the colors for each scheme .chartForegroundStyleScale([ "RocketSim" : .blue, "Stock Analyzer": .red ])
Наконец, вы можете захотеть показать группы рядом друг с другом. Это можно сделать с помощью модификатора позиции:
Chart(buildActivities) { buildActivity in BarMark( x: .value("Date", buildActivity.date, unit: .day), y: .value("Total Count", buildActivity.numberOfBuilds) ) /// Show a different color for each scheme .foregroundStyle( by: .value("Scheme", buildActivity.scheme) ) /// Show bars side by side .position( by: .value("Scheme", buildActivity.scheme), axis: .horizontal, span: .ratio(1) ) } /// Customize the colors for each scheme .chartForegroundStyleScale([ "RocketSim" : .blue, "Stock Analyzer": .red ])
Значение axis
определяет, будут ли столбики показаны друг над другом (вертикальные) или рядом друг с другом (горизонтальные). Span
позволяет управлять шириной каждого отдельного столбика. Полученная гистограмма выглядит следующим образом:
Заключение
Swift Charts позволяет просто визуализировать данные в виде гистограмм. Хотя в этой статье мы рассмотрели только основы, вы уже можете увидеть достойный результат. Вы можете настраивать цвет столбиков, группировать значения по определенным категориям и управлять диапазоном отображаемых данных.
Спасибо!