Chart.jsで作る「kintoneのダッシュボード」

※当記事の内容はサポート対象外です

こんにちは。武井です。

ダッシュボードの季節ですね。

kintoneのグラフ解析

kintoneの標準グラフにはHigh Chartsが採用されているようです。

High Chartsの特徴としては、

  • 見た目が綺麗
  • 使用に便利
  • カスタムに融通が利く

と最強らしいのですが、有料です。

一方、今回使用するChart.jsは無料チャートライブラリの中では一強の様相を呈しています。
ただし、Chart.jsはやや融通の利かない部分があります。

ダッシュボード作ってみた

201609131013

こんなん作ってみました。

詳しくは下記記事に譲りますが、
kintoneの標準機能にないグラフを厳選してChart.jsで実現したところが売りとなっております。

■Chart.jsを使ってダッシュボードを作ってみよう!
https://cybozudev.zendesk.com/hc/ja/articles/214479043

上記記事と参考画像では説明不足だったのですが、
下図のようなインタフェースも導入しているので、非常に使い勝手はよいです。

dashboard

右下部分が空白地帯でちょっと寂しいのは作業時間の関係上となります(゚゚;)

ダッシュボードをポータルに表示する

さて、kintone公式ではめったなことでDOMを操作してはいけないことになっていますので、
上記記事ではアプリ内にダッシュボードを表示していますが、
こちらでは例によってDOMをいじりまくることでポータルにダッシュボードを表示してしまう魔改造を披露していきたいと思います。

完成イメージ

portaldashboard

ぶっちゃけ使いやすさは圧倒的にこちらですね!

コードを一応すべて載せますが、アプリ版との違いは、ほぼほぼ「// 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,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');
//        $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的に考えて)。


⭐️トヨクモ kintone連携サービスのおすすめポイント⭐️
・kintone標準機能ではできない業務改善を実現
・カンタン・低コストで運用可能
・kintone1ドメインにつき1契約でOK
・10,000契約以上の実績・信頼
・30日間の無料お試しは何度でも可能