※当記事の内容はサポート対象外です
こんにちは。武井です。
ダッシュボードの季節ですね。
kintoneのグラフ解析
kintoneの標準グラフにはHigh Chartsが採用されているようです。
High Chartsの特徴としては、
- 見た目が綺麗
- 使用に便利
- カスタムに融通が利く
と最強らしいのですが、有料です。
一方、今回使用するChart.jsは無料チャートライブラリの中では一強の様相を呈しています。
ただし、Chart.jsはやや融通の利かない部分があります。
ダッシュボード作ってみた
こんなん作ってみました。
詳しくは下記記事に譲りますが、
kintoneの標準機能にないグラフを厳選してChart.jsで実現したところが売りとなっております。
■Chart.jsを使ってダッシュボードを作ってみよう!
https://cybozudev.zendesk.com/hc/ja/articles/214479043
上記記事と参考画像では説明不足だったのですが、
下図のようなインタフェースも導入しているので、非常に使い勝手はよいです。
右下部分が空白地帯でちょっと寂しいのは作業時間の関係上となります(゚゚;)
ダッシュボードをポータルに表示する
さて、kintone公式ではめったなことでDOMを操作してはいけないことになっていますので、
上記記事ではアプリ内にダッシュボードを表示していますが、
こちらでは例によってDOMをいじりまくることでポータルにダッシュボードを表示してしまう魔改造を披露していきたいと思います。
完成イメージ
ぶっちゃけ使いやすさは圧倒的にこちらですね!
コードを一応すべて載せますが、アプリ版との違いは、ほぼほぼ「// URLが変更される場合のチャート書き直し処理」からcreateSlider関数までの部分のみです。
(function() { "use strict"; // 販売実績アプリID var SALES_APPID = 70; // 試用申し込み管理アプリID var TRIAL_APPID = 71; var oneTimeFlg = true; var chart1, chart2, chart3; var onceFlg = true; /* 【参考】ドーナツグラフの各項目を常に表示 Chart.pluginService.register({ beforeRender: function (chart) { if (chart.config.options.showAllTooltips) { chart.pluginTooltips = []; chart.config.data.datasets.forEach(function (dataset, i) { chart.getDatasetMeta(i).data.forEach(function (sector, j) { chart.pluginTooltips.push(new Chart.Tooltip({ _chart: chart.chart, _chartInstance: chart, _data: chart.data, _options: chart.options.tooltips, _active: [sector] }, chart)); }); }); chart.options.tooltips.enabled = false; } }, afterDraw: function (chart, easing) { if (chart.config.options.showAllTooltips) { if (!chart.allTooltipsOnce) { if (easing !== 1) return; chart.allTooltipsOnce = true; } chart.options.tooltips.enabled = true; Chart.helpers.each(chart.pluginTooltips, function (tooltip) { tooltip.initialize(); tooltip.update(); tooltip.pivot(); tooltip.transition(easing).draw(); }); chart.options.tooltips.enabled = false; } } });*/ // URLが変更される場合のチャート書き直し処理 window.onhashchange = firstFunc; // ポータルを最初に読み込んだ時のチャート表示処理 window.onload = firstFunc; function firstFunc() { if (onceFlg) { if (location.href.indexOf("/#/portal") > 0) { onceFlg = false; var portalInterval = setInterval(function () { if ($(".ocean-portal-announcement .gaia-argoui-widget-menu").length > 0) { clearInterval(portalInterval); $(".ocean-portal-announcement .gaia-argoui-widget-menu").css("display", "block"); $(".ocean-portal-announcement .gaia-argoui-widget-menu").append('<div id="slider" style="margin-left:30px"></div><br /><p id="p1" style="margin-left:30px;">■売上高(前年同月比)</p><div id="canvas1Div" style="margin-left:30px;"><canvas id="canvas1"></canvas></div><br /><p id="p2" style="margin-left:30px;">■売上高・試用申込数</p><div id="canvas2Div" style="margin-left:30px;"><canvas id="canvas2"></canvas></div><br /><p id="p3" style="margin-left:30px;">■製品別売上高</p><div id="canvas3Div" style="margin-left:30px"><canvas id="canvas3"></canvas></div>'); createCompareGraph(); // お知らせを更新した場合等、URLが変わらずに画面が更新されるパターンでアプリ一覧を表示し直す処理 var rePortalInterval = setInterval(function () { if ($("#slider").length === 0) { clearInterval(rePortalInterval); oneTimeFlg = true; firstFunc(); } }, 500); } }, 100); } } } function createSlider() { $("#slider").dateRangeSlider(); $("#slider").dateRangeSlider( "option", { bounds: { min: moment().add(-5, 'years').startOf("month").toDate(), max: moment().startOf("month").toDate() }, step: { months: 1 }, range: { min: {months: 11}, max: {months: 11} }, formatter: function(val) { return moment(val).format("YYYY年M月"); } } ).bind("userValuesChanged", function(e, data) { // スライダーを動かした場合 createCompareGraph(data.values.min, data.values.max); }); reset(); oneTimeFlg = false; } function reset() { // スライダーの初期位置 $("#slider").dateRangeSlider("values", moment().add(-1, 'years').startOf("month").toDate(), moment().startOf("month").toDate()); // スライダーの位置を微調整 $("#slider").css("margin-bottom", "20px"); } function createCompareGraph(min, max) { //setLoading(); var maxMonth, maxMonth2, minMonth, minMonth2, elevenMonthsBefore, tenMonthsBefore, nineMonthsBefore, eightMonthsBefore, sevenMonthsBefore, sixMonthsBefore, fiveMonthsBefore, fourMonthsBefore, threeMonthsBefore, twoMonthsBefore, oneMonthBefore, thisMonth; if (max) { maxMonth = '"' + moment(max).endOf("month").format('YYYY-MM-DD') + '"'; maxMonth2 = moment(max).add(-12, "months").endOf("month").format('YYYY-MM-DD'); elevenMonthsBefore = moment(max).add(-11, 'months').format("M月"); tenMonthsBefore = moment(max).add(-10, 'months').format("M月"); nineMonthsBefore = moment(max).add(-9, 'months').format("M月"); eightMonthsBefore = moment(max).add(-8, 'months').format("M月"); sevenMonthsBefore = moment(max).add(-7, 'months').format("M月"); sixMonthsBefore = moment(max).add(-6, 'months').format("M月"); fiveMonthsBefore = moment(max).add(-5, 'months').format("M月"); fourMonthsBefore = moment(max).add(-4, 'months').format("M月"); threeMonthsBefore = moment(max).add(-3, 'months').format("M月"); twoMonthsBefore = moment(max).add(-2, 'months').format("M月"); oneMonthBefore = moment(max).add(-1, 'months').format("M月"); thisMonth = moment(max).format("M月"); } else { maxMonth = "THIS_MONTH()"; maxMonth2 = moment().add(-12, "months").endOf("month").format('YYYY-MM-DD'); elevenMonthsBefore = moment().add(-11, 'months').format("M月"); tenMonthsBefore = moment().add(-10, 'months').format("M月"); nineMonthsBefore = moment().add(-9, 'months').format("M月"); eightMonthsBefore = moment().add(-8, 'months').format("M月"); sevenMonthsBefore = moment().add(-7, 'months').format("M月"); sixMonthsBefore = moment().add(-6, 'months').format("M月"); fiveMonthsBefore = moment().add(-5, 'months').format("M月"); fourMonthsBefore = moment().add(-4, 'months').format("M月"); threeMonthsBefore = moment().add(-3, 'months').format("M月"); twoMonthsBefore = moment().add(-2, 'months').format("M月"); oneMonthBefore = moment().add(-1, 'months').format("M月"); thisMonth = moment().format("M月"); } if (min) { minMonth = moment(min).format('YYYY-MM-DD'); minMonth2 = moment(min).add(-12, "months").startOf("month").format('YYYY-MM-DD'); } else { minMonth = moment().add(-11, "months").startOf("month").format('YYYY-MM-DD'); minMonth2 = moment().add(-23, "months").startOf("month").format('YYYY-MM-DD'); } // 今月から一年前までのレコード取得 fetchRecords(SALES_APPID, '日付 <= ' + maxMonth + ' and 日付 >= "' + minMonth + '" order by 日付 asc').then(function(canvas1Rec) { var data = []; data[elevenMonthsBefore] = 0; data[tenMonthsBefore] = 0; data[nineMonthsBefore] = 0; data[eightMonthsBefore] = 0; data[sevenMonthsBefore] = 0; data[sixMonthsBefore] = 0; data[fiveMonthsBefore] = 0; data[fourMonthsBefore] = 0; data[threeMonthsBefore] = 0; data[twoMonthsBefore] = 0; data[oneMonthBefore] = 0; data[thisMonth] = 0; for (var i = 0; i < canvas1Rec.length; i++) { var month; var date = canvas1Rec[i].日付.value.split("-"); if (date[1].charAt(0) === "0") { month = date[1].charAt(1) + "月"; } else { month = date[1] + "月"; } data[month] += parseInt(canvas1Rec[i].販売額.value, 10); } var eventuallyThisYearData = [data[elevenMonthsBefore], data[tenMonthsBefore], data[nineMonthsBefore], data[eightMonthsBefore], data[sevenMonthsBefore], data[sixMonthsBefore], data[fiveMonthsBefore], data[fourMonthsBefore], data[threeMonthsBefore], data[twoMonthsBefore], data[oneMonthBefore], data[thisMonth]]; fetchRecords(SALES_APPID, '日付 <= "' + maxMonth2 + '" and 日付 >= "' + minMonth2 + '" order by 日付 asc').then(function(canvas1Rec2) { fetchRecords(TRIAL_APPID, '日付 <= ' + maxMonth + ' and 日付 >= "' + minMonth + '" order by 日付 asc').then(function(canvas2Rec) { data = refreshData(data); // 前年同月比グラフのデータ作成 for (var j = 0; j < canvas1Rec2.length; j++) { var month2; var date2 = canvas1Rec2[j].日付.value.split("-"); if (date2[1].charAt(0) === "0") { month2 = date2[1].charAt(1) + "月"; } else { month2 = date2[1] + "月"; } data[month2] += parseInt(canvas1Rec2[j].販売額.value, 10); } var eventuallyLastYearData = [data[elevenMonthsBefore], data[tenMonthsBefore], data[nineMonthsBefore], data[eightMonthsBefore], data[sevenMonthsBefore], data[sixMonthsBefore], data[fiveMonthsBefore], data[fourMonthsBefore], data[threeMonthsBefore], data[twoMonthsBefore], data[oneMonthBefore], data[thisMonth]]; data = refreshData(data); // ミックスドグラフのデータ作成 for (var k = 0; k < canvas2Rec.length; k++) { var month3; var date3 = canvas2Rec[k].日付.value.split("-"); if (date3[1].charAt(0) === "0") { month3 = date3[1].charAt(1) + "月"; } else { month3 = date3[1] + "月"; } data[month3] += 1; } var eventuallyTrialData = [data[elevenMonthsBefore], data[tenMonthsBefore], data[nineMonthsBefore], data[eightMonthsBefore], data[sevenMonthsBefore], data[sixMonthsBefore], data[fiveMonthsBefore], data[fourMonthsBefore], data[threeMonthsBefore], data[twoMonthsBefore], data[oneMonthBefore], data[thisMonth]]; // ドーナツグラフのデータ作成 var prodData = []; var prodLabels = []; for (var l = 0; l < canvas1Rec.length; l++) { var prod = canvas1Rec[l].製品名.value; if (typeof (prodData[prod]) === "undefined") { prodData[prod] = 0; prodLabels.push(prod); } prodData[prod] += parseInt(canvas1Rec[l].販売額.value, 10); } var eventuallyByProductData = []; // 製品背景色 var prodBGColorMST = { プリントクリエイター: "rgba(54, 162, 235, 0.4)", フォームクリエイター: "rgba(255, 99, 132, 0.4)", kBackup: "rgba(0, 100, 0, 0.4)", kViewer: "rgba(255, 60, 255, 0.4)", タイムスタンプ: "rgba(255, 255, 0, 0.4)", メールワイズ: "rgba(255, 112, 0, 0.4)", ガルーン: "rgba(60, 60, 120, 0.4)", kintone: "rgba(255, 0, 0, 0.4)", 安否確認: "rgba(0, 255, 255, 0.4)" }; // 【参考】製品縁取り色 /*var prodBDColorMST = { プリントクリエイター:"rgba(54, 162, 235, 1)", フォームクリエイター:"rgba(255,99,132,1)", kBackup:"rgba(0, 170, 0, 1)", kViewer:"rgba(255, 170, 255, 1)", タイムスタンプ:"rgba(255, 255, 0, 1)", メールワイズ:"rgba(255, 112, 0, 1)", ガルーン:"rgba(100, 0, 0, 1)", kintone:"rgba(255, 184, 184, 1)", 安否確認:"rgba(0, 255, 255, 1)" };*/ var prodBGColor = []; //var prodBDColor = []; // 降順にソート prodLabels.sort(function(a, b) { if (prodData[a] > prodData[b]) { return -1; } if (prodData[a] < prodData[b]) { return 1; } return 0; }); for (var m = 0; m < prodLabels.length; m++) { eventuallyByProductData.push(prodData[prodLabels[m]]); prodBGColor.push(prodBGColorMST[prodLabels[m]]); // 【参考】縁取り色をつける場合 //prodBDColor.push(prodBDColorMST[prodLabels[m]]); // 【参考】ランダムで配色する場合の処理 //prodBGColor.push(dynamicColors()); //prodBDColor.push(dynamicColors()); } // 前年同月比グラフを描画 var ctx = document.getElementById("canvas1"); if (chart1) { chart1.destroy(); } chart1 = new Chart(ctx, { type: 'bar', data: { labels: [elevenMonthsBefore, tenMonthsBefore, nineMonthsBefore, eightMonthsBefore, sevenMonthsBefore, sixMonthsBefore, fiveMonthsBefore, fourMonthsBefore, threeMonthsBefore, twoMonthsBefore, oneMonthBefore, thisMonth], datasets: [ { label: '前年同月売上', data: eventuallyLastYearData, backgroundColor: "rgba(54, 162, 235, 0.2)", borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }, { label: min ? moment(min).format('YYYY年M月~') + moment(max).format('YYYY年M月売上') : moment().add(-11, "months").format('YYYY年M月~') + moment().format('YYYY年M月売上'), data: eventuallyThisYearData, backgroundColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255,99,132,1)', borderWidth: 1 } ] }, options: { scales: { yAxes: [{ display: true, scaleLabel: { display: true, labelString: '売上', fontFamily: 'monospace' }, ticks: { beginAtZero: true, maxTicksLimit: 8, callback: function(value) { return value + '万円'; } } }] }, tooltips: { enabled: true, mode: 'single', callbacks: { title: function(tooltipItems, titleData) { var val = $("#slider").dateRangeSlider("values"); var min2 = moment(val.min); var tmp = tooltipItems[0].xLabel.split("月"); var first = moment(min2.format("YYYY-") + tmp[0] + '-1', 'YYYY-M-D'); if (first.isBetween(min2, moment(val.max), null, '[]')) { if (tooltipItems[0].datasetIndex === 0) { return min2.add(-1, 'years').format("YYYY年") + tmp[0] + '月'; } return min2.format("YYYY年") + tmp[0] + '月'; } if (tooltipItems[0].datasetIndex === 0) { return min2.format("YYYY年") + tmp[0] + '月'; } return min2.add(1, 'years').format("YYYY年") + tmp[0] + '月'; }, label: function(tooltipItems, data3) { return tooltipItems.yLabel + '万円'; } } } } }); // mixedグラフを描画 var ctx2 = document.getElementById("canvas2"); if (chart2) { chart2.destroy(); } chart2 = new Chart(ctx2, { type: 'bar', data: { labels: [elevenMonthsBefore, tenMonthsBefore, nineMonthsBefore, eightMonthsBefore, sevenMonthsBefore, sixMonthsBefore, fiveMonthsBefore, fourMonthsBefore, threeMonthsBefore, twoMonthsBefore, oneMonthBefore, thisMonth], datasets: [ { yAxisID: "y-axis-1", type: 'line', label: '試用申込数', data: eventuallyTrialData, backgroundColor: "rgba(54, 162, 235, 0.2)", borderColor: 'rgba(54, 162, 235, 1)', borderWidth: 1 }, { yAxisID: "y-axis-0", type: 'bar', label: min ? moment(min).format('YYYY年M月~') + moment(max).format('YYYY年M月売上') : moment().add(-11, "months").format('YYYY年M月~') + moment().format('YYYY年M月売上'), data: eventuallyThisYearData, backgroundColor: 'rgba(255, 99, 132, 0.2)', borderColor: 'rgba(255,99,132,1)', borderWidth: 1 } ] }, options: { scales: { yAxes: [{ position: "left", id: "y-axis-0", display: true, scaleLabel: { display: true, labelString: '売上', fontFamily: 'monospace' }, ticks: { beginAtZero: true, maxTicksLimit: 8, callback: function(value) { return value + '万円'; } } }, { position: "right", id: "y-axis-1", display: true, scaleLabel: { display: true, labelString: '試用申込数', fontFamily: 'monospace' }, ticks: { beginAtZero: true, maxTicksLimit: 6 } }] }, tooltips: { enabled: true, mode: 'single', callbacks: { title: function(tooltipItems, data4) { var val = $("#slider").dateRangeSlider("values"); var min3 = moment(val.min); var tmp = tooltipItems[0].xLabel.split("月"); var first = moment(min3.format("YYYY-") + tmp[0] + '-1', 'YYYY-M-D'); if (first.isBetween(min3, moment(val.max), null, '[]')) { return min3.format("YYYY年") + tmp[0] + '月'; } return min3.add(1, 'years').format("YYYY年") + tmp[0] + '月'; }, label: function(tooltipItems, data5) { if (tooltipItems.datasetIndex === 0) { return '試用申込数:' + tooltipItems.yLabel; } return '売上:' + tooltipItems.yLabel + '万円'; } } } } }); // ドーナツグラフを描画 var ctx3 = document.getElementById("canvas3"); if (chart3) { chart3.destroy(); } chart3 = new Chart(ctx3, { type: 'doughnut', data: { labels: prodLabels, datasets: [ { label: min ? moment(min).format('YYYY年M月~') + moment(max).format('YYYY年M月売上') : moment().add(-11, "months").format('YYYY年M月~') + moment().format('YYYY年M月売上'), data: eventuallyByProductData, backgroundColor: prodBGColor, //borderColor: prodBDColor, borderWidth: 1 } ] }, options: { showAllTooltips: true, animation: { animateScale: true }, tooltips: { callbacks: { title: function(tooltipItems, data6) { return data6.labels[tooltipItems[0].index]; }, label: function(tooltipItems, data7) { var sum = 0; for (var n = 0; n < data7.datasets[0].data.length; n++) { sum += data7.datasets[0].data[n]; } var per = Math.round((data7.datasets[0].data[tooltipItems.index] / sum * 100)); return per + '% ' + data7.datasets[0].data[tooltipItems.index] + '万円'; } } } } }); // グラフのデフォルトフォントサイズ Chart.defaults.global.defaultFontSize = 14; // 期間指定スライダーの横幅調整 $("#slider").css("width", "90%"); // スライダーの作成は画面読み込み時のみ if (oneTimeFlg) { createSlider(); } onceFlg = true; //removeLoading(); }); }); }); } // data配列の中身を消す関数 function refreshData(data) { for (var key in data) { data[key] = 0; } return data; } // 全レコード取得関数 function fetchRecords(appId, query, opt_offset, opt_limit, opt_records) { var offset = opt_offset || 0; var limit = opt_limit || 100; var allRecords = opt_records || []; var params = { app: appId, query: query + ' limit ' + limit + ' offset ' + offset }; return kintone.api('/k/v1/records', 'GET', params).then(function(resp) { allRecords = allRecords.concat(resp.records); if (resp.records.length === limit) { return fetchRecords(appId, query, offset + limit, limit, allRecords); } return allRecords; }); } // ローディング画面を出す関数 // function setLoading() { // var $body = $('body'); // $body.css('width', '100%'); // // var $loading = $('<div>').attr('id', 'loading').attr('class', 'loading') // .attr('style', 'width: 100%; height: 100%; position:absolute;' + // ' top:0; left:0; text-align:center; background-color:#666666; opacity:0.6; z-index: 9;'); // var $div = $('<div>').attr('id', 'imgBox').attr('style', 'width: 100%; height: 100%;'); // var $img = $('<img>').attr('src', 'data:image/gif;base64,R0lGODlhZABkAPQAAAAAAP///3BwcJaWlsjIyMLCwqKiouLi4uzs7NLS0qqqqrKysoCAgHh4eNra2v///4iIiLq6uvT09AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAHAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zfMgoDw0csAgSEh/JBEBifucRymYBaaYzpdHjtuhba5cJLXoHDj3HZBykkIpDWAP0YrHsDiV5faB3CB3c8EHuFdisNDlMHTi4NEI2CJwWFewQuAwtBMAIKQZGSJAmVelVGEAaeXKEkEaQSpkUNngYNrCWEpIdGj6C3IpSFfb+CAwkOCbvEy8zNzs/Q0dLT1NUrAgOf1kUMBwjfB8rbOQLe3+C24wxCNwPn7wrjEAv0qzMK7+eX2wb0mzXu8iGIty1TPRvlBKazJgBVnBsN8okbRy6VgoUUM2rcyLGjx48gQ4ocSbKkyZMoJf8JMFCAwAJfKU0gOUDzgAOYHiE8XDGAJoKaalAoObHERFESU0oMFbF06YikKQQsiKCJBYGaNR2ocPr0AQCuQ8F6Fdt1rNeuLSBQjRDB3qSfPm1uPYvUbN2jTO2izQs171e6J9SuxXjCAFaaQYkC9ku2MWCnYR2rkDqV4IoEWG/O5fp3ceS7nuk2Db0YBQS3UVm6xBmztevXsGPLnk27tu3buHOvQU3bgIPflscJ4C3D92/gFNUWgHPj2G+bmhkWWL78xvPjDog/azCdOmsXzrF/dyYgAvUI7Y7bDF5N+QLCM4whM7BxvO77+PPr38+//w4GbhSw0xMQDKCdJAwkcIx2ggMSsQABENLHzALILDhMERAQ0BKE8IUSwYILPjEAhCQ2yMoCClaYmA8NQLhhh5I0oOCCB5rAQI0mGEDiRLfMQhWOI3CXgIYwotBAA/aN09KQCVw4m4wEMElAkTEhIWUCSaL0IJPsySZVlC/5J+aYZJZppgghAAAh+QQABwABACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zfMhAIw0csAgQDhESCGAiM0NzgsawOolgaQ1ldIobZsAvS7ULE6BW5vDynfUiFsyVgL58rwQLxOCzeKwwHCIQHYCsLbH95Dg+OjgeAKAKDhIUNLA2JVQt4KhGPoYuSJEmWlgYuSBCYLRKhjwikJQqnlgpFsKGzJAa2hLhEuo6yvCKUv549BcOjxgOVhFdFdbAOysYNCgQK2HDMVAXexuTl5ufo6err7O3kAgKs4+48AhEH+ATz9Dj2+P8EWvET0YDBPlX/Eh7i18CAgm42ICT8l2ogAAYPFSyU0WAiPjcDtSkwIHCGAAITE/+UpCeg4EqTKPGptEikpQEGL2nq3Mmzp8+fQIMKHUq0qNGjSJO6E8DA4RyleQw4mOqgk1F4LRo4OEDVwTQUjk48MjGWxC6zD0aEBbBWbdlJBhYsAJlC6lSuDiKoaOuWbdq+fMMG/us37eCsCuRaVWG3q94UfEUIJlz48GHJsND6VaFJ8UEAWrdS/SqWMubNgClP1nz67ebIJQTEnduicdWDZ92aXq17N+G1kV2nwEqnqYGnUJMrX868ufPn0KNLn069Or+N0hksSFCArkWmORgkcJCgvHeWCiIYOB9jAfnx3D+fE5A+woKKNSLAh4+dXYMI9gEonwoKlPeeON8ZAOCgfTc0UB5/OiERwQA5xaCJff3xM6B1HHbo4YcghigiNXFBhEVLGc5yEgEJEKBPFBBEUEAE7M0yAIs44leTjDNGUKEkBrQopDM+NFDAjEf+CMiNQhJAWpE8zqjkG/8JGcGGIjCQIgoMyOhjOkwNMMCWJTTkInJZNYAlPQYU4KKT0xnpopsFTKmUPW8ScOV0N7oJ53TxJAbBmiMWauihiIIYAgAh+QQABwACACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/8AZo4BAFBjBpI5xKBYPSKWURnA6CdNszGrVeltc5zcoYDReiXDCBSkQCpDxShA52AuCFoQribMKEoGBA3IpdQh2B1h6TQgOfisDgpOQhSMNiYkIZy4CnC0Ek4IFliVMmnYGQAmigWull5mJUT6srRGwJESZrz+SrZWwAgSJDp8/gJOkuaYKwUADCQ4JhMzW19jZ2tvc3d7f4NoCCwgPCAs4AwQODqrhIgIOD/PzBzYDDgfsDgrvAAX0AqKjIW0fuzzhJASk56CGwXwOah2bGLBGQX0H31Gch6CGgYf93gGkOJCGgYIh3/8JUBjQHg6J/gSMlBABob+bOHPq3Mmzp8+fQIMKHUq0qNEUAiBAOHZ0RYN10p41PZGg6jQHNk/M07q1BD2vX0l0BdB1rIiKKhgoMMD0BANpVqmpMHv2AVm7I7aa1Yu3bl6+YvuuUEDYXdq40qqhoHu38d+wfvf2pRjYcYq1a0FNg5vVBGPAfy03lhwa8mjBJxqs7Yzi6WapgemaPh0b9diythnjSAqB9dTfwIMLH068uPHjyJMrX84cnIABCwz4Hj4uAYEEeHIOMAAbhjrr1lO+g65gQXcX0a5fL/nOwIL3imlAUG/d8DsI7xfAlEFH/SKcEAywHw3b9dbcgQgmqOByggw26KAIDAxwnnAGEGAhe0AIoEAE0mXzlBsWTojDhhFwmE0bFroR3w8RLNAiLtg8ZaGFbfVgwIv2WaOOGzn+IIABCqx4TRk1pkXYgMQNUUAERyhnwJIFFNAjcTdGaWJydCxZ03INBFjkg2CGKeaYCYYAACH5BAAHAAMALAAAAABkAGQAAAX/ICCOZGmeaKqubOu+cCzPdG3feK7vfO//wBnDUCAMBMGkTkA4OA8EpHJKMzyfBqo2VkBcEYWtuNW8HsJjoIDReC2e3kPEJRgojulVPeFIGKQrEGYOgCoMBwiJBwx5KQMOkJBZLQILkAuFKQ2IiYqZjQANfA4HkAltdKgtBp2tA6AlDJGzjD8KrZ0KsCSipJCltT63uAiTuyIGsw66asQHn6ACCpEKqj8DrQevxyVr0D4NCgTV3OXm5+jp6uvs7e7v6gIQEQkFEDgNCxELwfACBRICBtxGQ1QCPgn6uRsgsOE9GgoQ8inwLV2ChgLRzKCHsI9Cdg4wBkxQw9LBPhTh/wG4KHIODQYnDz6Ex1DkTCEL6t189w+jRhsf/Q04WACPyqNIkypdyrSp06dQo0qdSrWqVUcL+NER0MAa1AYOHoh9kKCiiEoE6nl1emDsWAIrcqYlkDKF2BNjTeQl4bbEXRF//47oe8KABLdjg4qAOTcBAcWAH+iVLBjA3cqXJQ/WbDkzX84oFCAey+wEg8Zp136e3Pnz3sitN28mDLsyiQWjxRo7EaFxXRS2W2OmDNqz7NrDY5swkPsB5FC91a6gHRm08OKvYWu3nd1EW8Rw9XA1q1TAd7Flr76wo1W9+/fw48ufT7++/fv48+s/wXUABPLwCWAAAQRiolQD/+FDIKRdBOz0TjgKkGNDAwsSSJBKEESowHOUEFjEY0lJEyGAegyw4G5HNcAAiS0g2ACL+8Uo44w01mjjjTi+wMCKMs5TQAQO+iCPAQme00AEP/4IIw0DZLVAkLA0kGQBBajGQ5MLKIDiMUcmGYGVO0CQZXvnCIAkkFOsYQCH0XQVAwP+sRlgVvssadU8+6Cp3zz66JmfNBFE8EeMKrqZ46GIJqrooi6EAAAh+QQABwAEACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/0Baw2BoBI88g2N5MCCfNgZz6WBArzEl1dHEeluGw9Sh+JpTg+1y8GpABGdWQxFZWF0L7nLhEhAOgBFwcScNCYcOCXctAwsRbC5/gIGEJwuIh3xADJOdg5UjEQmJowlBYZ2AEKAkeZgFQZypB0asIgyYCatBCakEtiQMBQkFu0GGkwSfwGYQBovM0dLT1NXW19jZ2ts+AgYKA8s0As6Q3AADBwjrB9AzogkEytwN6uvs4jAQ8fxO2wr3ApqTMYAfgQSatBEIeK8MjQEHIzrUBpAhgoEyIkSct62BxQP5YAhoZCDktQEB2/+d66ZAQZGVMGPKnEmzps2bOHPq3Mmzp88v5Iz9ZLFAgtGLjCIU8IezqFGjDzCagCBPntQSDx6cyKoVa1avX0mEBRB2rAiuXU00eMoWwQoF8grIW2H2rFazX/HeTUs2Lde+YvmegMCWrVATC+RWpSsYsN6/I/LyHYtWL+ATAwo/PVyCatWrgU1IDm3Zst2+k/eiEKBZgtsVA5SGY1wXcmTVt2v77aq7cSvNoIeOcOo6uPARAhhwPs68ufPn0KNLn069uvXrfQpklSAoRwOT1lhXdgC+BQSlEZZb0175QcJ3Sgt039Y+6+sZDQrI119LW/26MUQQ33zaSFDfATY0kFh2euewV9l748AkwAGVITidAAA9gACE2HXo4YcghijiiN0YEIEC5e3QAAP9RWOiIxMd0xKK0zhSRwRPMNCSAepVYoCNTMnoUopxNDLbEysSuVIDLVLXyALGMSfAAgsosICSP01J5ZXWQUBlj89hSeKYZJZpJoghAAAh+QQABwAFACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/0Bag8FoBI+8RmKZMCKfNQbTkSAIoNgYZElNOBjZcGtLLUPE6JSg601cXQ3IO60SQAzyF9l7bgkMbQNzdCUCC1UJEWAuAgOCLwYOkpIDhCdbBIiVQFIOB5IHVpYlBpmmC0EMk6t9oyIDplUGqZ+ek06uAAwEpqJBCqsOs7kjDAYLCoM/DQa1ycSEEBCL0NXW19jZ2tvc3d7fPwJDAsoz4hC44AIFB+0R5TGwvAbw2Q0E7fnvNQIEBbwEqHVj0A5BvgPpYtzj9W+TNwUHDR4QqBAgr1bdIBzMlzCGgX8EFtTD1sBTPgQFRv/6YTAgDzgAJfP5eslDAAMFDTrS3Mmzp8+fQIMKHUq0qNGjSJMisYNR6YotCBAE9GPAgE6fEKJqnbiiQYQCYCmaePDgBNmyJc6mVUuC7Ai3AOC+ZWuipAStUQusGFDgawQFK+TOjYtWhFvBhwsTnlsWseITDfDibVoCAtivgFUINtxY8VnHiwdz/ty2MwoBkrVSJtEAbNjAjxeDnu25cOLaoU2sSa236wCrKglvpss5t/DHcuEO31z57laxTisniErganQSNldf3869u/fv4MOLH0++vHk/A5YQeISjQfBr6yTIl5/Sxp2/76sNmM9fuwsDESyAHzgJ8DdfbzN4JWCkBBFYd40DBsqXgA0DMIhMfsQUGGEENjRQIR4v7Rehfy9gWE18/DkEnh0RJELieTDGKOOMNAa1DlkS1Bceap894ICJUNjhCJAyFNAjWahAA8ECTKrow5FkIVDNMcgMAwSUzFnCAJMLvHiDBFBKWQ1LLgERAZRJBpVTiQ70eMBQDSigAHSnLYCAj2kCJYCcBjwz3h98EnkUM1adJ2iNiCaq6KKLhgAAIfkEAAcABgAsAAAAAGQAZAAABf8gII5kaZ5oqq5s675wLM90bd94ru987//AoHAYEywShIWAyKwtCMjEokmFCaJQwrLKVTWy0UZ3jCqAC+SfoCF+NQrIQrvFWEQU87RpQOgbYg0MMAwJDoUEeXoiX2Z9iT0LhgmTU4okEH0EZgNCk4WFEZYkX5kEEEJwhoaVoiIGmklDEJOSgq0jDAOnRBBwBba3wcLDxMXGx8jJysvMzUJbzgAGn7s2DQsFEdXLCg4HDt6cNhHZ2dDJAuDqhtbkBe+Pxgze4N8ON+Tu58jp6+A3DPJtU9aNnoM/OBrs4wYuAcJoPYBBnEixosWLGDNq3Mixo8ePIEOKxGHEjIGFKBj/DLyY7oDLA1pYKIgQQcmKBw9O4MxZYmdPnyRwjhAKgOhQoCcWvDyA4IC4FAHtaLvJM2hOo0WvVs3K9ehRrVZZeFsKc0UDmnZW/jQhFOtOt2C9ingLt+uJsU1dolmhwI5NFVjnxhVsl2tdwkgNby0RgSyCpyogqGWbOOvitlvfriVc2LKKli9jjkRhRNPJ0ahTq17NurXr17Bjy55NG0UDBQpOvx6AoHdTiTQgGICsrIFv3wdQvoCwoC9xZAqO+34Ow0DfBQ+VEZDeW4GNOgsWTC4WnTv1QQaAJ2vA9Hhy1wPaN42XWoD1Acpr69/Pv79/ZgN8ch5qBUhgoIF7BSMAfAT07TDAgRCON8ZtuDWYQwIQHpigKAzgpoCEOGCYoQQJKGidARaaYB12LhAwogShKMhAiqMc8JYDNELwIojJ2EjXAS0UCOGAywxA105EjgBBBAlMZdECR+LESmpQRjklagxE+YB6oyVwZImtCUDAW6K51mF6/6Wp5po2hAAAIfkEAAcABwAsAAAAAGQAZAAABf8gII5kaZ5oqq5s675wLM90bd94ru987//AoHAYE0AWC4iAyKwNCFDCoEmFCSJRQmRZ7aoaBWi40PCaUc/o9OwTNMqvhiE84LYYg4GSnWpEChEQMQ0MVlgJWnZ8I36AgHBAT4iIa4uMjo9CC5MECZWWAI2Oij4GnaefoEcFBYVCAlCIBK6gIwwNpEACCgsGubXAwcLDxMXGx8jJysvMZ7/KDAsRC5A1DQO9z8YMCQ4J39UzBhHTCtrDAgXf3gkKNg3S0hHhx9zs3hE3BvLmzOnd6xbcYDCuXzMI677RenfOGAR1CxY26yFxosWLGDNq3Mixo8ePIEOKHEmyZDEBAwz/GGDQcISAlhMFLHBwwIEDXyyOZFvx4MGJnj5LABU6lETPEUcBJEVa9MQAm1Ad0CshE4mCqUaDZlWqlatXpl9FLB26NGyKCFBr3lyxCwk1nl3F+iwLlO7crmPr4r17NqpNAzkXKMCpoqxcs0ftItaaWLFhEk9p2jyAlSrMukTjNs5qOO9hzipkRiVsMgXKwSxLq17NurXr17Bjy55Nu7ZtIoRWwizZIMGB3wR2f4FQuVjv38gLCD8hR8HVg78RIEdQnAUD5woqHjMgPfpv7S92Oa8ujAHy8+TZ3prYgED331tkp0Mef7YbJctv69/Pv7//HOlI0JNyQ+xCwHPACOCAmV4S5AfDAAhEKF0qfCyg14BANCChhAc4CAQCFz6mgwIbSggYKCGKmAOJJSLgDiggXiiBC9cQ5wJ3LVJ4hoUX5rMCPBIEKcFbPx5QYofAHKAXkissIKSQArGgIYfgsaGAki62JMCTT8J0Wh0cQcClkIK8JuaYEpTpGgMIjIlAlSYNMKaOq6HUpgQIgDkbAxBAAOd/gAYqKA0hAAAh+QQABwAIACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcChrQAYNotImiBQKi+RyCjM4nwOqtmV4Og3bcIpRuDLEaBNDoTjDGg1BWmVQGORDA2GfnZusCxFgQg17BAUEUn4jEYGNQwOHhhCLJFYREQpDEIZ7ipUCVgqfQAt7BYOVYkduqq6vsLGys7S1tre4ubq7UwIDBn04DAOUuwJ7CQQReDUMC8/FuXrJydE0Bs92uwvUBAnBNM7P4LcK3ufkMxDAvMfnBbw9oQsDzPH3+Pn6+/z9/v8AAwocSLCgwYO9IECwh9AEBAcJHCRq0aAOqRMPHmDMaCKjRhIeP47gKIIkyZEeU/8IgMiSABc2mlacRAlgJkebGnGizCmyZk8UAxIIHdoqRR02LGaW5AkyZFOfT5c6pamURFCWES+aCGWgKIqqN3uGfapzqU+xTFEIiChUYo+pO0uM3fnzpMm6VUs8jDixoVoIDBj6HUy4sOHDiBMrXsy4sWMSTSRkLCD4ltcZK0M+QFB5lgIHEFPNWKB5cq7PDg6AFh0DQem8sVaCBn0gQY3XsGExSD0bdI0DryXgks0bYg3SpeHhQj07HQzgIR10lmWAr/MYC1wjWDD9sffv4MOLR3j1m5J1l/0UkMCevXIgDRIcQHCAQHctENrrv55D/oH/B7ynnn7t2fYDAwD+R59zVmEkQCB7BvqgQIIAphdGBA9K4JILcbzQAID0/cfgFvk9aE0KDyFA34kp+AdgBK4MQKCAKEqg4o0sniBAAQBS9goEESQQQY4nJHDjjRGy0EBg/Rx55GFO3ngYAVFuWBiCRx4w4kENFKBiAVuOJ+aYZIoZAgAh+QQABwAJACwAAAAAZABkAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcChrMBoNotImUCwiiuRyCoNErhEIdduCPJ9arhgleEYWgrHaxIBAGDFkep1iGBhzobUQkdJLDAtOYUENEXx8fn8iBguOBkMNiImLJF6CA0MCBYh9lSMCEAYQikAMnBFwn2MCRquvsLGys7S1tre4ubq7vDqtpL5HvAIGBMYDeTTECgrJtwwEBcYEzjIMzKO7A9PGpUUGzN61EMbSBOIxoei0ZdOQvTuhAw3V8Pb3+Pn6+/z9/v8AAwocSBCQo0wFUwhI8KDhgwPrerUSUK8EAYcOD/CTRCABGhUMMGJ8d6JhSZMlHP+mVEkCJQCULkVgVFggQUcCC1QoEOlQQYqYMh+8FDrCZEyjRIMWRdoyaZ2bNhOoOmGAZ8OcKIAO3bqUpdKjSXk25XqiQdSb60JaJWlCK9OlZLeChetVrtMSm85iTXFRpMafdYfefRsUqEuYg7WWkGTTk4qFGB1EHEavIpuDCTNr3sy5s+fPoEOLHk063YCaCZD1mlpjk4TXrwtYjgWh5gLWMiDA3o3wFoQECRwExw2jwG7YCXDlFS58r4wEx187wMUgOHDgEWpEiC4h+a281h34pKE7em9b1YUDn7xiwHHZugKdYc/CSoIss0vr38+/v//RTRAQhRIC4AHLAAcgoCCkAuf50IACDkTYzCcCJLiggvTRAKEDB0TIFh0GXLjgeD4wwGGEESaQIREKiKggiT2YiOKJxI0xgIsIfKgCPS+YFWGHwq2oiYULHpCfCFZE+FELBszoQIN0NEDkATWaIACHB2TpwJEAEGOdaqsIMIACYLKwQJZoHuDcCkZweUsBaCKQJQGfEZBmlgV8ZkCCceqYWXVpUgOamNEYIOR/iCaq6KIAhAAAIfkEAAcACgAsAAAAAGQAZAAABf8gII5kaZ5oqq5s675wLM90bd94ru987//AoHBIExCPOMhiAUE6ZYLl0vissqJSqnWLGiwUA64Y1WiMfwKGmSgwgM+otsKwFhoWkYgBbmIo/gxEeXgLfCUNfwp1QQp4eoaHakdRelqQl5iZmpucnZ6foKGioz8LCA8IC5akOAcPr68Oq6CzMguwuAWjEBEFC4syDriwEqICvcg2w7iiDQXPBRHAMKfLD8bR0RE2t8u6ogzPEU01AsK4ErWdAtMzxxKvBeqs9PX29/j5+vv8/f7/AAMKNAEBwryBJAYgkMCwEMIUAxhKlOBQn4AB0cKsWDiRYTsRr07AMjGSBDOT10D/pgyJkmUXAjAJkEMBoaPEmSRTogTgkue1niGB6hwptAXMAgR8qahpU4JGkTpHBI06bGdRlSdV+lQRE6aCjU3n9dRatCzVoT/NqjCAFCbOExE7VoQ6tqTUtC2jbtW6967eE2wjPFWhUOLchzQNIl7MuLHjx5AjS55MubJlGQ3cKDj4kMEBBKARDKZ1ZwDnFQI+hwb9UZMAAglgb6uhcDXor6EUwN49GoYC26AJiFoQu3jvF7Vt4wZloDjstzBS2z7QWtPuBKpseA594LinAQYU37g45/Tl8+jTq19fmUF4yq8PfE5QPQeEAgkKBLpUQL7/BEJAkMCADiSwHx8NyIeAfH8IHOgDfgUm4MBhY0Dg34V7ACEhgQnMxocACyoon4M9EBfhhJdEcOEBwrkwQAQLeHcCAwNKSEB9VRzjHwHmAbCAA0Ci6AIDeCjiGgQ4jjBAkAcAKSNCCgQZ5HKOGQBkk0Bm+BgDUjZJYmMGYOmAlpFlRgd7aKap5poyhAAAIfkEAAcACwAsAAAAAGQAZAAABf8gII5kaZ5oqq5s675wLM90bd94ru987//AoHBIExCPOIHB0EA6ZUqFwmB8WlkCqbR69S0cD8SCy2JMGd3f4cFmO8irRjPdW7TvEaEAYkDTTwh3bRJCEAoLC35/JIJ3QgaICwaLJYGND0IDkRCUJHaNBXoDAxBwlGt3EqadRwIFEmwFq6y0tba3uLm6u7y9viYQEQkFpb8/AxLJybLGI7MwEMrSA81KEQNzNK/SyQnGWQsREZM1CdzJDsYN4RHh2TIR5xLev1nt4zbR59TqCuOcNVxxY1btXcABBBIkGPCsmcOHECNKnEixosWLGDNq3MjxCIRiHV0wIIAAQQKAIVX/MDhQsqQElBUFNFCAjUWBli0dGGSEyUQbn2xKOOI5IigAo0V/pmBQIEIBgigg4MS5MynQoz1FBEWKtatVrVuzel2h4GlTflGntnzGFexYrErdckXaiGjbEv6aEltxc+qbFHfD2hUr+GvXuIfFmmD6NEJVEg1Y4oQJtC3ixDwtZzWqWfGJBksajmhA0iTllCk+ikbNurXr17Bjy55Nu7bt20HkKGCwOiWDBAeC63S4B1vvFAIIBF+e4DEuAQsISCdHI/Ly5ad1QZBeQLrzMssRLFdgDKF0AgUUybB+/YB6XiO7Sz9+QkAE8cEREPh+y8B5hjbYtxxU6kDQAH3I7XEgnG4MNujggxBGCAVvt2XhwIUK8JfEIX3YYsCFB2CoRwEJJEQAgkM0ANyFLL7HgwElxphdGhCwCKIDLu4QXYwEUEeJAAnc6EACOeowAI8n1TKAjQ74uIIAo9Bnn4kRoDgElEEmQIULNWY54wkMjAKSLQq+IMCQQwZp5UVdZpnkbBC4OeSXqCXnJpG1qahQc7c1wAADGkoo6KCEFrpCCAA7AAAAAAAAAAAA'); // $loading.append($div.append($img)); // $body.append($loading); // // $('#imgBox').attr('style', 'margin-top: ' + Math.floor($('#loading').height() / 2) + 'px;'); // // $body.css('position', 'fixed'); // // var autoRemoveCnt = 0; // var autoRemoveInterval = setInterval(function() { // autoRemoveCnt++; // if (autoRemoveCnt > 9) { // clearInterval(autoRemoveInterval); // removeLoading(); // } // }, 1000); // } // ローディング画面を消す関数 // function removeLoading() { // var $loading = $('.loading'); // $loading.remove(); // // var $body = $('body'); // $body.css('position', ''); // } // 【参考】ドーナツグラフの各製品色をランダムに決定する関数 // function dynamicColors() { // var r = Math.floor(Math.random() * 255); // var g = Math.floor(Math.random() * 255); // var b = Math.floor(Math.random() * 255); // return "rgb(" + r + "," + g + "," + b + ")"; // } })();
感想
他のデベロッパーサイト記事と比して私の記事のコード量に圧倒されますね(゜o ゜;)
Chart.jsではできないことが割と多いので、「いかにChart.jsを要件に寄せるか」ではなく「いかに要件をChart.jsに寄せるか」が問われます(SIer的に考えて)。