<!doctype html> <html> <head> <script src="//cdn.anychart.com/js/7.4.0/anychart.min.js"></script> <style> html, body, #container { width: 100%; height: 100%; margin: 0; padding: 0; } </style> </head> <body> <div id="container"></div> <script type="text/javascript"> // Filters var territoryFilter = null; var platformFilter = null; var categoryFilter = null; // Charting objects var unitsChart = null; var territoryChart = null; var platformChart = null; var categoryChart = null; var unitSeries = null; var territorySeries = null; var platformSeries = null; var categorySeries = null; var helpLabel = null; // Colors var unitSeriesColor = 'rgb(102, 143, 169)'; var barsSeriesColor = 'rgb(233, 234, 237)'; var hoverBarsSeriesColor = 'rgb(255, 225, 105)'; var barTitleColor = 'rgb(85, 85, 85)'; var helpTextColor = 'rgb(85, 85, 85)'; var helpBgStroke = 'rgb(221, 221, 221)'; var helpBgFill = 'rgb(249, 250, 251)'; // Raw dashboard data, see data format in the end of the file var rawData = generateData(); anychart.onDocumentReady(function() { var title; // Create stage for all charting objects stage = acgraph.create('container'); // Create area chart unitsChart = anychart.area(); // Set chart to render on stage unitsChart.container(stage); // Set chart size and position unitsChart.bounds(0, 0, '100%', '50%'); // Set chart title text title = unitsChart.title(); title.text('Software Sales Dashboard Units per Day'); title.fontSize(16); title.fontWeight('normal'); // Set chart title position title.margin().top(10).bottom(10); // Remove left chart padding unitsChart.padding().left(0); // Disable chart background unitsChart.background().enabled(false); // Set chart grid settings var grid = unitsChart.grid(); grid.enabled(true); grid.oddFill('none'); grid.evenFill('none'); var extraGrid = unitsChart.grid(1); extraGrid.enabled(false); var minorGrid = unitsChart.minorGrid(); minorGrid.enabled(false); // Create yAxis var yAxis = unitsChart.yAxis(); yAxis.title().text('Units'); yAxis.stroke('none'); yAxis.ticks().enabled(false); yAxis.minorTicks().enabled(false); yAxis.labels().padding().right(5); // Create xAxis var xAxis = unitsChart.xAxis(); xAxis.title().enabled(false); xAxis.staggerMode(false); var monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; xAxis.labels().textFormatter(function() { var date = new Date(this.value); return monthNames[date.getMonth()] + ' ' + date.getDate() + ' ' + date.getFullYear(); }); // Create step area series unitSeries = unitsChart.stepArea(); unitSeries.color(unitSeriesColor); unitSeries.tooltip().contentFormatter(function() { return String(this.value); }); // Create bar chart territoryChart = anychart.bar(); // Set chart to render on stage territoryChart.container(stage); // Set chart size and position territoryChart.bounds('1%', '52%', '33%', '30%'); // Set chart settings common for all bar charts in dashboard setupBarChartSettings(territoryChart); // Set chart title text title = territoryChart.title(); title.text('Territory'); title.fontWeight('normal'); title.fontColor(barTitleColor); title.fontSize('16px'); // Set chart title position settings title.padding(0, 0, 0, 80); title.align('left'); // Create bar series territorySeries = territoryChart.bar(); territorySeries.name('territories'); // Set series settings common for all bar series in the dashboard setupBarSeriesSettings(territorySeries); // Create bar chart platformChart = anychart.bar(); // Set chart to render on stage platformChart.container(stage); // Set chart size and position platformChart.bounds('34%', '52%', '32%', '30%'); // Set chart settings common for all bar charts in the dashboard setupBarChartSettings(platformChart); // Set chart title text title = platformChart.title(); title.text('Platform'); title.fontWeight('normal'); title.fontColor(barTitleColor); title.fontSize('16px'); // Set chart title position settings title.align('left'); title.padding(0, 0, 0, 40); // Create bar series platformSeries = platformChart.bar(); platformSeries.name('platforms'); // Set series settings common for all bar series in the dashboard setupBarSeriesSettings(platformSeries); // Create help label helpLabel = platformChart.label(); //set label text settings helpLabel.text('Click Bars to Filter'); helpLabel.fontColor(helpTextColor); helpLabel.fontSize(10); helpLabel.fontWeight('normal'); //set label position settings helpLabel.position('centerbottom'); helpLabel.anchor('centerbottom'); helpLabel.offsetY(-20); helpLabel.padding(3, 3, 3, 3); // Set label background settings var labelBackground = helpLabel.background(); labelBackground.enabled(true); labelBackground.fill(helpBgFill); labelBackground.stroke(helpBgStroke); // Create bar chart categoryChart = anychart.bar(); // Set chart to render on stage categoryChart.container(stage); // Set chart size and position categoryChart.bounds('66%', '52%', '33%', '30%'); // Set chart settings common for all bar charts in the dashboard setupBarChartSettings(categoryChart); // Set chart title text title = categoryChart.title(); title.text('Category'); title.fontWeight('normal'); title.fontColor(barTitleColor); title.fontSize('16px'); // Set chart title position title.align('left'); title.padding(0, 0, 0, '90px'); // Create bar series categorySeries = categoryChart.bar(); categorySeries.name('categories'); // Set series settings common for all bar series in the dashboard setupBarSeriesSettings(categorySeries); updateData(); // Initiate all charts drawing unitsChart.draw(); territoryChart.draw(); platformChart.draw(); categoryChart.draw(); }); // Setup same settings for all charts function setupBarSeriesSettings(series) { series.color(barsSeriesColor) series.tooltip().contentFormatter(function() { return String(this.value); }); series.listen('pointClick', function(e) { var series = e.target; var seriesName = series.name(); var categoryName = e.iterator.get('x'); switch (seriesName) { case 'territories': territoryFilter = (territoryFilter && territoryFilter == categoryName) ? null : categoryName; break; case 'platforms': platformFilter = (platformFilter && platformFilter == categoryName) ? null : categoryName; break; case 'categories': categoryFilter = (categoryFilter && categoryFilter == categoryName) ? null : categoryName; break; } updateData(); }); } /** * Set the same settings for all charts (assuming it is Bar Chart). * @param {anychart.cartesian.Chart} chart Chart to set settings. */ function setupBarChartSettings(chart) { // Disable axes titles chart.xAxis().title().enabled(false); chart.yAxis().enabled(false); // Disable grids chart.grid().enabled(false); chart.grid(1).enabled(false); chart.minorGrid().enabled(false); // Set bar position chart.barsPadding(.2); chart.barGroupsPadding(0.5); // Set background, padding and margin settings chart.background().enabled(false); chart.padding(0); chart.margin(0); chart.margin().bottom(20); } /** * Apply filters to raw data. * Set data to charts in the following format: * * var unitData = [ * //timestamp value * [1409529600000, 100], * [1409616000000, 200], * [1409702400000, 300] * ]; * var barData = [ * {x: 'Category Name 1', value: 100, fill: 'rgb(233, 234, 237)', stroke: 'anychart.color.darken(rgb(233, 234, 237))'}, * {x: 'Category Name 2', value: 200, fill: 'rgb(233, 234, 237)', stroke: 'anychart.color.darken(rgb(233, 234, 237))'}, * {x: 'Category Name 3', value: 300, fill: 'rgb(233, 234, 237)', stroke: 'anychart.color.darken(rgb(233, 234, 237))'} * ]; * */ function updateData() { var unitMap = {}; var territoryMap = {}; var platformMap = {}; var categoryMap = {}; for (var i = 0, count = rawData.length; i < count; i++) { var dataItem = rawData[i]; var fitTerritoryFilter = !territoryFilter || (territoryFilter && territoryFilter == dataItem['territory']); var fitPlatformFilter = !platformFilter || (platformFilter && platformFilter == dataItem['platform']); var fitCategoryFilter = !categoryFilter || (categoryFilter && categoryFilter == dataItem['category']); if (fitTerritoryFilter && fitPlatformFilter && fitCategoryFilter) { var unitsMapItem = unitMap[dataItem.x]; if (unitsMapItem) { unitMap[dataItem.x] = [dataItem.x, unitsMapItem[1] + dataItem.value]; } else { unitMap[dataItem.x] = [dataItem.x, dataItem.value]; } } if (fitPlatformFilter && fitCategoryFilter) { var territoryMapItem = territoryMap[dataItem.territory]; if (territoryMapItem) { territoryMapItem.value += dataItem.value; } else { territoryMapItem = {x: dataItem.territory, value: dataItem.value}; territoryMap[dataItem.territory] = territoryMapItem; } territoryMapItem['fill'] = territoryMapItem.x == territoryFilter ? hoverBarsSeriesColor : undefined; territoryMapItem['stroke'] = territoryMapItem.x == territoryFilter ? anychart.color.darken(hoverBarsSeriesColor) : undefined; } if (fitTerritoryFilter && fitCategoryFilter) { var platformMapItem = platformMap[dataItem.platform]; if (platformMapItem) { platformMapItem.value += dataItem.value; } else { platformMapItem = {x: dataItem.platform, value: dataItem.value}; platformMap[dataItem.platform] = platformMapItem; } platformMapItem['fill'] = platformMapItem.x == platformFilter ? hoverBarsSeriesColor : undefined; platformMapItem['stroke'] = platformMapItem.x == territoryFilter ? anychart.color.darken(hoverBarsSeriesColor) : undefined; } if (fitTerritoryFilter && fitPlatformFilter) { var categoryMapItem = categoryMap[dataItem.category]; if (categoryMapItem) { categoryMapItem += dataItem.value; } else { categoryMapItem = {x: dataItem.category, value: dataItem.value}; categoryMap[dataItem.category] = categoryMapItem; } categoryMapItem['fill'] = categoryMapItem.x == categoryFilter ? hoverBarsSeriesColor : undefined; categoryMapItem['stroke'] = categoryMapItem.x == territoryFilter ? anychart.color.darken(hoverBarsSeriesColor) : undefined; } } var territoryData = getValues(territoryMap); //console.log(territoryData); //uncomment to log data format var platformData = getValues(platformMap); //console.log(platformData); //uncomment to log data format var categoryData = getValues(categoryMap); //console.log(categoryData); //uncomment to log data format var unitData = getValues(unitMap); //console.log(unitData); //uncomment to log data format territorySeries.data(territoryData); platformSeries.data(platformData); categorySeries.data(categoryData); unitSeries.data(unitData); } /** * Generate data in the following format: * var data = [ * {x: Date.UTC(2014, 8, 1), value: 700, territory: 'Europe', platform: 'iPhone', category: 'Games'}, * {x: Date.UTC(2014, 8, 1), value: 200, territory: 'Europe', platform: 'iPad', category: 'Games'}, * {x: Date.UTC(2014, 8, 1), value: 400, territory: 'Europe', platform: 'Desktop', category: 'Games'} * ]; * @return {Array.<Object>} */ function generateData() { var data = []; var dates = [ Date.UTC(2014, 8, 1), Date.UTC(2014, 8, 2), Date.UTC(2014, 8, 3), Date.UTC(2014, 8, 4), Date.UTC(2014, 8, 5), Date.UTC(2014, 8, 6), Date.UTC(2014, 8, 7), Date.UTC(2014, 8, 8), Date.UTC(2014, 8, 9) ]; var territories = ['Europe', 'Asia Pacific', 'USA and Canada']; var platforms = ['iPhone', 'iPad', 'Desktop']; var categories = ['Games', 'Social Networking', 'Photo & Video']; for (var d = 0, datesCount = dates.length; d < datesCount; d++) { for (var t = 0, territoriesCount = territories.length; t < territoriesCount; t++) { for (var p = 0, platformsCount = platforms.length; p < platformsCount; p++) { for (var c = 0, categoriesCount = categories.length; c < categoriesCount; c++) { data.push({ x: dates[d], value: Math.floor((Math.random() * 100) + 1), territory: territories[t], platform: platforms[p], category: categories[c] }); } } } } return data; } /** * Return Object values as array. * @param {Object} obj * @return {Array} */ function getValues(obj) { var res = []; var i = 0; for (var key in obj) { res[i++] = obj[key]; } return res; } </script> </body> </html>