chart.jsでバブルチャートをスライダー（スライドバー？）でグリグリ動かす前編

# 目指す姿（前編）

以下のように、chart.jsのバブルチャートをスライダー（スライドバー？）でグリグリ動かす。

![02_bubblechart_add_slider.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402061/24b7b6dc-d5af-7ffa-f74e-a2c789430d5f.gif)

後編では、このスライダーをボタン一つで自動再生できるようにしました！
https://qiita.com/supinngassenn/items/ee0cf76d58adf2a300a7

# 説明

## ステップ１

まずは以下のように、普通にバブルチャートを作成します。

<img width="1078" alt="スクリーンショット 2019-07-11 22.12.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402061/cb9aeb1a-a2a9-0968-ad6f-707a98aefab8.png">

上図のコード↓

```
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
<title>グラフ</title> 
</head>
  <body>
<h1>バブルチャート</h1>
    <canvas id="myBubbleChart"></canvas>
      
    <!-- CDN -->

    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js"></script>

    <script>
        
        // バブルチャート本体
        var ctx = document.getElementById("myBubbleChart");
        var myBubbleChart = new Chart(ctx, {
            type: 'bubble',
            data: {
                datasets: [
                    {
                        label:"プロジェクト1",
                        backgroundColor: "rgba(128,128,0,0.8)",
                        data:[{x: 15,y: 60,r: 35}]
                    },
                    {
                        label:"プロジェクト2",
                        backgroundColor: "rgba(255,255,0,0.8)",
                        data:[{x: 45,y: 50,r: 15}]
                    },
                    {
                        label:"プロジェクト3",
                        backgroundColor: "rgba(0,255,255,0.8)",
                        data:[{x: 25,y: 20,r: 30}]
                    },
                    {
                        label:"プロジェクト4",
                        backgroundColor: "rgba(0,255,0,0.8)",
                        data:[{x: 10,y: 70,r: 25}]
                    },
                    {
                        label:"プロジェクト5",
                        backgroundColor: "rgba(255,0,0,0.8)",
                        data:[{x: 30,y: 40,r: 30}]
                    },
                    {
                        label:"プロジェクト6",
                        backgroundColor: "rgba(0,0,255,0.8)",
                        data:[{x: 35,y: 50,r: 15}]
                    },
                    {
                        label:"プロジェクト7",
                        backgroundColor: "rgba(0,128,0,0.8)",
                        data:[{x: 15,y: 25,r: 30}]
                    },
                    {
                        label:"プロジェクト8",
                        backgroundColor: "rgba(128,0,128,0.8)",
                        data:[{x: 34,y: 40,r: 25}]
                    },
                    {
                        label:"プロジェクト9",
                        backgroundColor: "rgba(0,0,128,0.8)",
                        data:[{x: 12,y: 15,r: 10}]
                    }
                ]
            },
            options: {
                title: {
                    display: true,
                    text: 'QCD状況（バブルが大きいほどコスト状況が悪い）'
                },
                scales: {
                    xAxes: [{
                        scaleLabel:{
                            display: true,
                            labelString: "進捗"
                        },
                        ticks: {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values){
                                return  value +  '%'
                            }
                        }
                    }],
                    yAxes: [{
                        scaleLabel:{
                            display: true,
                            labelString: "品質"
                        },
                        ticks: {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values){
                                return  value +  '%'
                            }
                        }
                    }]
                }
            },
        })
 
    </script>

  </body>
</html>
```

## ステップ２

次にデータを時系列で取れるように配列で格納し、それぞれのデータを取得する関数を定義します。また、スライダーの横に「4週間前、3週間前、2週間前、1週間前、現在」と表示するための配列と関数も用意します。

```
// バブルチャートのデータ定義（4週間前、3週間前、2週間前、1週間前、現在の順で格納）
        var data1 = [[{x: 15,y: 60,r: 35}],
        [{x: 21,y: 50,r: 32}],
        [{x: 36,y: 44,r: 24}],
        [{x: 46,y: 34,r: 34}],
        [{x: 56,y: 24,r: 58}]]

        var data2 = [[{x: 45,y: 50,r: 15}],
        [{x: 57,y: 60,r: 25}],
        [{x: 69,y: 70,r: 35}],
        [{x: 70,y: 80,r: 55}],
        [{x: 79,y: 83,r: 45}]]

        var data3 = [[{x: 25,y: 20,r: 30}],
        [{x: 35,y: 22,r: 32}],
        [{x: 55,y: 24,r: 34}],
        [{x: 60,y: 34,r: 39}],
        [{x: 65,y: 34,r: 30}]]

        var data4 = [[{x: 10,y: 70,r: 25}],
        [{x: 12,y: 72,r: 22}],
        [{x: 15,y: 74,r: 24}],
        [{x: 20,y: 84,r: 20}],
        [{x: 35,y: 74,r: 40}]]

        var data5 = [[{x: 30,y: 40,r: 30}],
        [{x: 51,y: 42,r: 32}],
        [{x: 60,y: 44,r: 34}],
        [{x: 70,y: 54,r: 34}],
        [{x: 73,y: 64,r: 54}]]

        var data6 = [[{x: 35,y: 50,r: 15}],
        [{x: 47,y: 60,r: 25}],
        [{x: 59,y: 70,r: 35}],
        [{x: 69,y: 80,r: 35}],
        [{x: 73,y: 70,r: 35}]]

        var data7 = [[{x: 15,y: 25,r: 30}],
        [{x: 17,y: 35,r: 40}],
        [{x: 28,y: 45,r: 50}],
        [{x: 30,y: 35,r: 60}],
        [{x: 40,y: 45,r: 70}]]

        var data8 = [[{x: 34,y: 40,r: 25}],
        [{x: 42,y: 50,r: 15}],
        [{x: 50,y: 60,r: 10}],
        [{x: 60,y: 70,r: 30}],
        [{x: 65,y: 45,r: 20}]]

        var data9 = [[{x: 12,y: 15,r: 10}],
        [{x: 17,y: 25,r: 20}],
        [{x: 38,y: 35,r: 30}],
        [{x: 40,y: 45,r: 30}],
        [{x: 45,y: 55,r: 30}]]

        // バブルチャートのデータ取得関数（添え字によって4週間前、3週間前、2週間前、1週間前、現在を切替）
        function get_data1(num) {            
            return data1[num];
        }
        function get_data2(num) {             
            return data2[num];
        }
        function get_data3(num) {             
            return data3[num];
        }
        function get_data4(num) {            
            return data4[num];
        }
        function get_data5(num) {             
            return data5[num];
        }
        function get_data6(num) {             
            return data6[num];
        }
        function get_data7(num) {             
            return data7[num];
        }
        function get_data8(num) {             
            return data8[num];
        }
        function get_data9(num) {             
            return data9[num];
        }
        
        // スライドバーのデータ定義と取得関数（添え字によって4週間前、3週間前、2週間前、1週間前、現在を切替）
        var bar_position = ['4週間前','3週間前','2週間前', '1週間前', '現在']
        function get_bar_position(num) {             
            return bar_position[num];
        }
        
        // バブルチャート本体
        var ctx = document.getElementById("myBubbleChart");
        var myBubbleChart = new Chart(ctx, {
            type: 'bubble',
            data: {
                datasets: [
                    {
                        label:"プロジェクト1",
                        backgroundColor: "rgba(128,128,0,0.8)",
                        data:get_data1(0)
                    },
                    {
                        label:"プロジェクト2",
                        backgroundColor: "rgba(255,255,0,0.8)",
                        data:get_data2(0)
                    },
                    {
                        label:"プロジェクト3",
                        backgroundColor: "rgba(0,255,255,0.8)",
                        data:get_data3(0)
                    },
                    {
                        label:"プロジェクト4",
                        backgroundColor: "rgba(0,255,0,0.8)",
                        data:get_data4(0)
                    },
                    {
                        label:"プロジェクト5",
                        backgroundColor: "rgba(255,0,0,0.8)",
                        data:get_data5(0)
                    },
                    {
                        label:"プロジェクト6",
                        backgroundColor: "rgba(0,0,255,0.8)",
                        data:get_data6(0)
                    },
                    {
                        label:"プロジェクト7",
                        backgroundColor: "rgba(0,128,0,0.8)",
                        data:get_data7(0)
                    },
                    {
                        label:"プロジェクト8",
                        backgroundColor: "rgba(128,0,128,0.8)",
                        data:get_data8(0)
                    },
                    {
                        label:"プロジェクト9",
                        backgroundColor: "rgba(0,0,128,0.8)",
                        data:get_data9(0)
                    }
                ]
            },
            options: {
                title: {
                    display: true,
                    text: 'QCD状況（バブルが大きいほどコスト状況が悪い）'
                },
                scales: {
                    xAxes: [{
                        scaleLabel:{
                            display: true,
                            labelString: "進捗"
                        },
                        ticks: {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values){
                                return  value +  '%'
                            }
                        }
                    }],
                    yAxes: [{
                        scaleLabel:{
                            display: true,
                            labelString: "品質"
                        },
                        ticks: {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values){
                                return  value +  '%'
                            }
                        }
                    }]
                }
            },
        })
```

## ステップ３

次にスライダーをHTML側で設置し、javaScript側でそのスライダーを動かしたときのイベントを定義します。
HTML側↓

```
<div class="slidecontainer" id="sliders">
        <input type="range" min="0" max="4" value="0" step="1" class="slider" id="slider_position">時系列 : <span id="val_position">4週間前</span><br/>
</div>
```

javaScript側↓

```
//バーの位置によってバブルチャートに表示するデータを切り替える
        function bubble_chart_move() {
            let position = document.getElementById("slider_position").value;     // sliderの値を取得
            document.getElementById("val_position").textContent = get_bar_position(position);      // 取得した値を"#val_position"のテキストに表示
            myBubbleChart.data.datasets[0].data = get_data1(position)
            myBubbleChart.data.datasets[1].data = get_data2(position)
            myBubbleChart.data.datasets[2].data = get_data3(position)
            myBubbleChart.data.datasets[3].data = get_data4(position)
            myBubbleChart.data.datasets[4].data = get_data5(position)
            myBubbleChart.data.datasets[5].data = get_data6(position)
            myBubbleChart.data.datasets[6].data = get_data7(position)
            myBubbleChart.data.datasets[7].data = get_data8(position)
            myBubbleChart.data.datasets[8].data = get_data9(position)
            myBubbleChart.update();
        }

        // スライダーを動かしたときのイベント
        var sliders = document.getElementById("sliders");
        sliders.addEventListener("input", function() {
            bubble_chart_move();
        }, false);
```

これで完成です！

# 最終形のコード

以下のコードをそのままコピペしてブラウザで表示すれば、実際に試すことができます。

```
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
<title>グラフ</title> 
</head>
  <body>
<h1>バブルチャート</h1>
    <canvas id="myBubbleChart"></canvas>
    <div class="slidecontainer" id="sliders">
        <input type="range" min="0" max="4" value="0" step="1" class="slider" id="slider_position">時系列 : <span id="val_position">4週間前</span><br/>
      </div>
      
    <!-- CDN -->

    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.bundle.js"></script>

    <script>

        // バブルチャートのデータ定義（4週間前、3週間前、2週間前、1週間前、現在の順で格納）
        var data1 = [[{x: 15,y: 60,r: 35}],
        [{x: 21,y: 50,r: 32}],
        [{x: 36,y: 44,r: 24}],
        [{x: 46,y: 34,r: 34}],
        [{x: 56,y: 24,r: 58}]]

        var data2 = [[{x: 45,y: 50,r: 15}],
        [{x: 57,y: 60,r: 25}],
        [{x: 69,y: 70,r: 35}],
        [{x: 70,y: 80,r: 55}],
        [{x: 79,y: 83,r: 45}]]

        var data3 = [[{x: 25,y: 20,r: 30}],
        [{x: 35,y: 22,r: 32}],
        [{x: 55,y: 24,r: 34}],
        [{x: 60,y: 34,r: 39}],
        [{x: 65,y: 34,r: 30}]]

        var data4 = [[{x: 10,y: 70,r: 25}],
        [{x: 12,y: 72,r: 22}],
        [{x: 15,y: 74,r: 24}],
        [{x: 20,y: 84,r: 20}],
        [{x: 35,y: 74,r: 40}]]

        var data5 = [[{x: 30,y: 40,r: 30}],
        [{x: 51,y: 42,r: 32}],
        [{x: 60,y: 44,r: 34}],
        [{x: 70,y: 54,r: 34}],
        [{x: 73,y: 64,r: 54}]]

        var data6 = [[{x: 35,y: 50,r: 15}],
        [{x: 47,y: 60,r: 25}],
        [{x: 59,y: 70,r: 35}],
        [{x: 69,y: 80,r: 35}],
        [{x: 73,y: 70,r: 35}]]

        var data7 = [[{x: 15,y: 25,r: 30}],
        [{x: 17,y: 35,r: 40}],
        [{x: 28,y: 45,r: 50}],
        [{x: 30,y: 35,r: 60}],
        [{x: 40,y: 45,r: 70}]]

        var data8 = [[{x: 34,y: 40,r: 25}],
        [{x: 42,y: 50,r: 15}],
        [{x: 50,y: 60,r: 10}],
        [{x: 60,y: 70,r: 30}],
        [{x: 65,y: 45,r: 20}]]

        var data9 = [[{x: 12,y: 15,r: 10}],
        [{x: 17,y: 25,r: 20}],
        [{x: 38,y: 35,r: 30}],
        [{x: 40,y: 45,r: 30}],
        [{x: 45,y: 55,r: 30}]]

        // バブルチャートのデータ取得関数（添え字によって4週間前、3週間前、2週間前、1週間前、現在を切替）
        function get_data1(num) {            
            return data1[num];
        }
        function get_data2(num) {             
            return data2[num];
        }
        function get_data3(num) {             
            return data3[num];
        }
        function get_data4(num) {            
            return data4[num];
        }
        function get_data5(num) {             
            return data5[num];
        }
        function get_data6(num) {             
            return data6[num];
        }
        function get_data7(num) {             
            return data7[num];
        }
        function get_data8(num) {             
            return data8[num];
        }
        function get_data9(num) {             
            return data9[num];
        }
        
        // スライドバーのデータ定義と取得関数（添え字によって4週間前、3週間前、2週間前、1週間前、現在を切替）
        var bar_position = ['4週間前','3週間前','2週間前', '1週間前', '現在']
        function get_bar_position(num) {             
            return bar_position[num];
        }
        
        // バブルチャート本体
        var ctx = document.getElementById("myBubbleChart");
        var myBubbleChart = new Chart(ctx, {
            type: 'bubble',
            data: {
                datasets: [
                    {
                        label:"プロジェクト1",
                        backgroundColor: "rgba(128,128,0,0.8)",
                        data:get_data1(0)
                    },
                    {
                        label:"プロジェクト2",
                        backgroundColor: "rgba(255,255,0,0.8)",
                        data:get_data2(0)
                    },
                    {
                        label:"プロジェクト3",
                        backgroundColor: "rgba(0,255,255,0.8)",
                        data:get_data3(0)
                    },
                    {
                        label:"プロジェクト4",
                        backgroundColor: "rgba(0,255,0,0.8)",
                        data:get_data4(0)
                    },
                    {
                        label:"プロジェクト5",
                        backgroundColor: "rgba(255,0,0,0.8)",
                        data:get_data5(0)
                    },
                    {
                        label:"プロジェクト6",
                        backgroundColor: "rgba(0,0,255,0.8)",
                        data:get_data6(0)
                    },
                    {
                        label:"プロジェクト7",
                        backgroundColor: "rgba(0,128,0,0.8)",
                        data:get_data7(0)
                    },
                    {
                        label:"プロジェクト8",
                        backgroundColor: "rgba(128,0,128,0.8)",
                        data:get_data8(0)
                    },
                    {
                        label:"プロジェクト9",
                        backgroundColor: "rgba(0,0,128,0.8)",
                        data:get_data9(0)
                    }
                ]
            },
            options: {
                title: {
                    display: true,
                    text: 'QCD状況（バブルが大きいほどコスト状況が悪い）'
                },
                scales: {
                    xAxes: [{
                        scaleLabel:{
                            display: true,
                            labelString: "進捗"
                        },
                        ticks: {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values){
                                return  value +  '%'
                            }
                        }
                    }],
                    yAxes: [{
                        scaleLabel:{
                            display: true,
                            labelString: "品質"
                        },
                        ticks: {
                            suggestedMax: 100,
                            suggestedMin: 0,
                            stepSize: 10,
                            callback: function(value, index, values){
                                return  value +  '%'
                            }
                        }
                    }]
                }
            },
        })

        //バーの位置によってバブルチャートに表示するデータを切り替える
        function bubble_chart_move() {
            let position = document.getElementById("slider_position").value;     // sliderの値を取得
            document.getElementById("val_position").textContent = get_bar_position(position);      // 取得した値を"#val_position"のテキストに表示
            myBubbleChart.data.datasets[0].data = get_data1(position)
            myBubbleChart.data.datasets[1].data = get_data2(position)
            myBubbleChart.data.datasets[2].data = get_data3(position)
            myBubbleChart.data.datasets[3].data = get_data4(position)
            myBubbleChart.data.datasets[4].data = get_data5(position)
            myBubbleChart.data.datasets[5].data = get_data6(position)
            myBubbleChart.data.datasets[6].data = get_data7(position)
            myBubbleChart.data.datasets[7].data = get_data8(position)
            myBubbleChart.data.datasets[8].data = get_data9(position)
            myBubbleChart.update();
        }

        // スライダーを動かしたときのイベント
        var sliders = document.getElementById("sliders");
        sliders.addEventListener("input", function() {
            bubble_chart_move();
        }, false);
 
    </script>

  </body>
</html>
```

後編では、このスライダーをボタン一つで自動再生できるようにしました！
https://qiita.com/supinngassenn/items/ee0cf76d58adf2a300a7

# 参考にしたサイト

* 基本的なバブルチャートの作り方
https://qiita.com/Haruka-Ogawa/items/392e26123f7e9618a47b

* スライダーの作り方
https://qiita.com/yohm/items/586690bf36efa0838e37