Разработка пользовательского интерфейса
Мне было поручено изменить дизайн представления записей домохозяйств для MortarStone. MortarStone — это платформа SaaS, которая позволяет некоммерческим организациям и церквям оценивать и управлять своими пожертвованиями, а просмотр записей домохозяйств — это место, где пользователи проверяют отдельных доноров. Неудивительно, что большая часть этого представления заключалась в том, чтобы показать, сколько пожертвовало каждое домохозяйство, когда они пожертвовали и какому фонду принадлежит пожертвование.
Предыдущая версия MortarStone показывала эту информацию в двух разных таблицах, но было много недостатков в таком отображении. Было легко посмотреть на отдельные случаи пожертвований, но табличный формат затруднял измерение роста с течением времени или сравнение сумм пожертвований по фондам. Это было проблемой, потому что одно из основных преимуществ нашего продукта заключается в том, что мы позволяем пользователям легко определять тенденции подарков и не только просматривать отдельные подарки, как вы можете в электронной таблице, но и четко показывать вам общую картину.
Я начал с каркасного решения. После нескольких итераций мы пришли к этому макету, который показывает наиболее важные общие данные о домохозяйстве вверху и некоторые статистические данные внизу. В середине мы хотели включить диаграмму пожертвований для проверки пожертвований как на макро-, так и на микроуровне. Я намеренно не тратил время на то, чтобы слишком много думать о том, как будет выглядеть или вести себя диаграмма, потому что я не хотел продавать идею дизайна нашим заинтересованным сторонам, а затем обнаруживать, что реализовать ее технически невозможно. Итак, на этапе проектирования я изложил основные элементы и доверил разработчику найти такое решение для создания диаграмм, которое было бы относительно простым в реализации, достаточно гибким, чтобы его можно было настроить в соответствии с нашими желаниями, и масштабируемым.
Разработан каркас без концепции диаграммы
Поиск подходящей библиотеки диаграмм
Раньше я создавал диаграммы с несколькими популярными библиотеками javascript, но то, что я пробовал раньше, меня не совсем устраивало ни с функциональной, ни с эстетической точки зрения — я искал новую библиотеку, и начались поиски.
После некоторого поиска хорошей библиотеки диаграмм я решил остановиться на замечательном C3.js. C3.js — это простая, чистая библиотека javascript, зависящая только от D3.js. У меня был некоторый опыт использования D3.js для создания пользовательских визуализаций с нуля, и каким бы замечательным ни был D3.js, я подумал, что создавать свои собственные диаграммы с нуля было бы излишним. C3.js был отличным решением, потому что он предлагает надежную коллекцию предварительно настроенных типов диаграмм и удобный API для выполнения некоторых общих настроек, но он просто использует D3.js под капотом, поэтому вы по-прежнему можете делать все что угодно. вы хотели бы напрямую через D3. Графики также были очень минималистичными, включали в себя сделанные со вкусом анимации из коробки и в целом выглядели великолепно!
Реализация диаграмм
Настроить графики не составило труда. Я установил и C3, и D3 с помощью Bower и был готов начать помещать наши данные в простые для понимания диаграммы. Я создал службу AngularJS под названием msCharts, которая обрабатывает все общие настройки диаграммы. Это включает в себя обеспечение видимости условных обозначений и меток диаграммы на мобильных устройствах, создание красивых описательных всплывающих подсказок и, по сути, получение данных из обычного массива и передачу их в C3.js в правильном синтаксисе.
Служба msCharts
'use strict'; angular.module('frontendCompanyApp') .service('msCharts', function ($window) { var self = this; // rotate and cull legend on small layouts var rotateDegrees = 0; var culling = false; var clientWidth = Math.max(document.documentElement.clientWidth, $window.innerWidth || 0); if (clientWidth < 960) { rotateDegrees = 60; culling = true; } this.create = function (id, format, xAxisLabels, segments) { function getFormat () { var formatSet; if (format === undefined) { formatSet = d3.format(','); } else if (format === 'days') { formatSet = function (data) { return data.toFixed() + ' days'; }; } else if (format === 'dollars') { formatSet = d3.format('$,.0f'); } else { formatSet = d3.format(format); } return formatSet; } var chart = c3.generate({ bindto: '#givingChart', data: { columns: [], groups: [segments], order: 'desc', }, legend: { item: { onclick: function (id) { chart.toggle(id); } } }, axis: { x: { type: 'category', categories: xAxisLabels, tick: { culling: culling, rotate: rotateDegrees } }, y: { tick: { format: getFormat() } } }, grid: { focus: { show: false } }, tooltip: { grouped: true, format: getFormat(), contents: function (data, defaultTitleFormat, defaultValueFormat, color) { var template = self.givingTooltipTemplate(data, xAxisLabels, color); return template; } } }); return chart; }; this.givingTooltipTemplate = function (data, xAxisLabels, color) { var total = 0; data.forEach(function (dataPoint) {total += dataPoint.value;}); var template = '' + '<md-card class="chart__tooltip">' + '<h3 class="chart__tooltip__header" layout="row" layout-align="start">' + '<div flex>' + xAxisLabels[data[0].index] + ' total:</div>' + '<div flex class="align-right"> $' + total.toLocaleString() + '</div>' + '</h3>' + '<div class="chart__tooltip__body" layout="column">'; data.forEach(function (dataPoint) { template += '' + '<div layout="row" layout-align="space-between start">' + '<div flex>' + '<div class="chart__tooltip__swatch" style="background-color: '+ color(dataPoint.id) + '"></div>' + dataPoint.name + '</div>' + '<div flex class="align-right"> $' + dataPoint.value.toLocaleString() + '</div>' + '</div>'; }); template += '</div></md-card>'; return template; }; });
После того, как это было настроено, все, что мне нужно было сделать, это получить данные с сервера и вызвать мой удобный сервисный метод msCharts.create().
Создание данных из данных сервера
var app = angular.module('frontendCompanyApp'); app.controller('HouseholdRecordCtrl', function ( $scope, $http, msCharts, $cookies ) { var self = this; this.getGiftsGroup = function (range) { // Save range preference via cookies $cookies.put('givingRange', range.key); self.givingChart.loading = true; self.givingChart.error = false; self.givingRange = range.label; $http.get('/api/v1/donors_service/donor_unit/donations/grouped', { params: { donor_unit_id: donorUnitId, type: range.key } }) .then(function (response) { self.givingChart.loading = false; createGiftsChart(response.data.grouped); }, function (error) { self.givingChart.loading = false; self.givingChart.error = true; console.log('Gifts grouped request error:', error); }); }; )};
Окончательный результат
Я выбрал диаграмму с областями с накоплением. Этот тип диаграммы представляет количество по оси Y по размеру области и позволяет увидеть, как различные типы данных составляют общую сумму. Это было отличное решение, потому что оно позволяет нашим пользователям просматривать пожертвования в целом, а также видеть, из каких средств состоит пожертвование. Наши пользователи были очень довольны тем, как получились диаграммы. Теперь они могут…
- Просматривайте пожертвования домохозяйства во времени
- Выберите для просмотра пожертвований за последние 12 месяцев, текущий год, месяц или квартал.
- Выберите, чтобы показать или скрыть отдельные средства
- Наведите указатель мыши на точки данных, чтобы открыть подробности
- Просмотр их графиков на мобильных устройствах