日付をX軸としたamChartsの折れ線グラフで初期表示(ズーム後)を直近の1週間表示に変更する

# 概要
[amCharts](https://www.amcharts.com/)の[Date Based Data](https://www.amcharts.com/demos/date-based-data/)を使用しグラフを作成します。
こちらのグラフは起動時に全体を表示し、”最終日からある割合”の日付をズームして表示します。（かっこいい）
Demo source
[![Image from Gyazo](https://i.gyazo.com/c2f3c2e4f80ee8e8deecf11c669de5eb.gif)](https://gyazo.com/c2f3c2e4f80ee8e8deecf11c669de5eb)
この**”最終日からある割合”**を**”直近の1週間”**に変更していきたいとおもいます。（上のDemo sourceのgifでは直近の8日にプロットされた値が表示されてますね）

##作成する前提
[amCharts](https://www.amcharts.com/)がCDNで読み込めている　
参考文献[amcharts 4 Demos を使ってグラフを作成](https://qiita.com/Ktym44977057/items/0766e4524f7cae1b8d5b)(amChartsの導入方法が記載されています）
使用するグラフの種類：[Date Based Data](https://www.amcharts.com/demos/date-based-data/)
使用するモデル:[Railsにて不連続な間隔(日付など)で投稿された値をamChartsを使って折れ線グラフを作成する。](https://qiita.com/pdmmcsfcs/items/95e06be830404e1230cb)において作成した体重管理アプリをモデルに作成します。コントローラーファイルなどの記述はこちらを参考にしてください。


##編集するファイル
・ビューファイル
###ビューファイル(Demo source)
まずは、Demo sourceがどういう構造になっているか見てみましょう。

```erb:demo.erb
<!-- Styles -->
<style>
#chartdiv {
  width: 100%;
  height: 500px;
}

</style>

<!-- Resources -->
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>

<!-- Chart code -->
<script>
am4core.ready(function() {

// Themes begin
am4core.useTheme(am4themes_animated);
// Themes end

// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);

// Add data
chart.data = [{
  "date": "2012-07-27",
  "value": 13
}, {
  "date": "2012-07-28",
  "value": 11
}, {
  "date": "2012-07-29",
  "value": 15
}, {
//~省略~
  "date": "2013-01-30",
  "value": 81
}];

// Set input format for the dates
chart.dateFormatter.inputDateFormat = "yyyy-MM-dd";

// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());

// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "value";
series.dataFields.dateX = "date";
series.tooltipText = "{value}"
series.strokeWidth = 2;
series.minBulletDistance = 15;

// Drop-shaped tooltips
series.tooltip.background.cornerRadius = 20;
series.tooltip.background.strokeOpacity = 0;
series.tooltip.pointerOrientation = "vertical";
series.tooltip.label.minWidth = 40;
series.tooltip.label.minHeight = 40;
series.tooltip.label.textAlign = "middle";
series.tooltip.label.textValign = "middle";

// Make bullets grow on hover
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.strokeWidth = 2;
bullet.circle.radius = 4;
bullet.circle.fill = am4core.color("#fff");

var bullethover = bullet.states.create("hover");
bullethover.properties.scale = 1.3;

// Make a panning cursor
chart.cursor = new am4charts.XYCursor();
chart.cursor.behavior = "panXY";
chart.cursor.xAxis = dateAxis;
chart.cursor.snapToSeries = series;

// Create vertical scrollbar and place it before the value axis
chart.scrollbarY = new am4core.Scrollbar();
chart.scrollbarY.parent = chart.leftAxesContainer;
chart.scrollbarY.toBack();

// Create a horizontal scrollbar with previe and place it underneath the date axis
chart.scrollbarX = new am4charts.XYChartScrollbar();
chart.scrollbarX.series.push(series);
chart.scrollbarX.parent = chart.bottomAxesContainer;

chart.events.on("ready", function () {
  dateAxis.zoom({start:0.79, end:1});
});

}); // end am4core.ready()
</script>

<!-- HTML -->
<div id="chartdiv"></div>
```
なんだか難しそうで、なにを書いているかパッとみたただけではわかりませんね。
ただ、データが記載されているところはわかるのではないでしょうか？

```erb:demo.erb
<script>
// Add data
chart.data = [{
  "date": "2012-07-27",
  "value": 13
}, {
  "date": "2012-07-28",
  "value": 11
}, {
  "date": "2012-07-29",
  "value": 15
}, {
//~省略~
  "date": "2013-01-30",
  "value": 81
}];
</script>
```
↑ここです。
この部分を体重管理アプリのモデルに合わせていきます。
###ビューファイル(本アプリ)
まずは、コントローラーから変数をもってきて算出までします。

```erb:index.erb
<script>
//JSON形式で値を渡す
const weights = <%== JSON.dump(@weights) %>;
const dates = <%== JSON.dump(@dates) %>;
//表示期間を計算
var firstDate = new Date(dates[0])　//一番最初
var lastDate = new Date(dates.slice(-1)[0])　//一番最後
var termDate= (lastDate - firstDate)/ 1000 / 60 / 60 / 24 + 1　//表示する期間
</script>
```
細かいところは[Railsにて不連続な間隔(日付など)で投稿された値をamChartsを使って折れ線グラフを作成する。](https://qiita.com/pdmmcsfcs/items/95e06be830404e1230cb)を参照してください。（本記事をそのままコピペしても動きません）
さて、Demo sourceのchart.dataの値を下記のように変えてください。

```erb:index.erb
<script>
// Add data
  chart.data = [];
  for (var j =0; j< weights.length; j++){
    for (var i = 0; i < termDate; i++) {
      var newDate = new Date(firstDate)
      newDate.setDate(newDate.getDate() + i); //初日からi日分たす
      if ((new Date(dates[j])) - (newDate)==0){
        weight =weights[j]
        chart.data.push({
            date: newDate,
            weight: weight
        });
      }
    }
  }
</script>
```
valueは[Railsにて不連続な間隔(日付など)で投稿された値をamChartsを使って折れ線グラフを作成する。](https://qiita.com/pdmmcsfcs/items/95e06be830404e1230cb)のときと同様にweightに変更してます。weightの変更箇所はその他にもあるのですべて置換してあげてください。

##初期表示(ズーム後)を直近の1週間表示にする
本記事の本題です。
まずはDemo sourceからズームっぽい記述を探してみましょう。後方から９行目付近をみてください。

```erb:demo.erb
<script>
chart.events.on("ready", function () {
  dateAxis.zoom({start:0.79, end:1});
});
</script>
```
**{start:0.79, end:1}**の数値を試しに**{start:0, end:1}**かえてみてください。
変えるときは、[【小ネタ】amChartsのDemo sourceをVScodeなどのエディタにコピペせず、ブラウザ上でプロパティを変更し表示を確認する方法](https://qiita.com/pdmmcsfcs/items/a772dd1777182ebc0c28)を使うと便利です。
[![Image from Gyazo](https://i.gyazo.com/fd7d8d145ac380f1fe5db2ffa49abff0.png)](https://gyazo.com/fd7d8d145ac380f1fe5db2ffa49abff0)
zoomされず、全体が表示されました。
ということは、startの数値を変更すれば**直近の1週間**が表示できそうです。

全体の日数は**termDate**という変数で取得できてるので、
1週間は全体の日数のどれくらいの割合か出してみます。
例：termDateが70日の場合
式: 7/termDate=0.1
0.1という数値をstartに入れては駄目です。なぜならstartは0に近いほど、小さい値（日付）を取得します。
なので0.1を入れると0.1≦x≦1の範囲になり（endが1の場合)、一番古い日付から1週間後から最新の日付を範囲としてしまいます。
では、どうするかというと1から引いてあげれば良いです。

｛start:1-7/termDate, end:1}としてあげます。

こうすることで0.9≦x≦1となり、直近の1週間の割合がだせます。
最後にビューファイルの全体を記載します。

```erb:index.erb
<!-- Styles -->
<style>
#chartdiv {
  width: 100%;
  height: 500px;
}

</style>

<!-- Resources -->
<script src="https://www.amcharts.com/lib/4/core.js"></script>
<script src="https://www.amcharts.com/lib/4/charts.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/kelly.js"></script>
<script src="https://www.amcharts.com/lib/4/themes/animated.js"></script>

<!-- Chart code -->
<script>
am4core.ready(function() {

// Themes begin
am4core.useTheme(am4themes_kelly);
am4core.useTheme(am4themes_animated);
// Themes end

// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
const weights = <%== JSON.dump(@weights) %>;
const dates = <%== JSON.dump(@dates) %>;

var firstDate = new Date(dates[0])
var lastDate = new Date(dates.slice(-1)[0])
var termDate= (lastDate - firstDate)/ 1000 / 60 / 60 / 24 + 1

// Add data
  chart.data = [];
  for (var j =0; j< weights.length; j++){
    for (var i = 0; i < termDate; i++) {
      var newDate = new Date(firstDate)
      newDate.setDate(newDate.getDate() + i); //初日からi日分たす
      if ((new Date(dates[j])) - (newDate)==0){
        weight =weights[j]
        chart.data.push({
            date: newDate,
            weight: weight
        });
      }
    }
  }

// Set input format for the dates
chart.dateFormatter.inputDateFormat = "yyyy-MM-dd";

// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());

// Create series
var series = chart.series.push(new am4charts.LineSeries());
series.dataFields.valueY = "weight";
series.dataFields.dateX = "date";
series.tooltipText = "{weight}"
series.strokeWidth = 2;
series.minBulletDistance = 15;

// Drop-shaped tooltips
series.tooltip.background.cornerRadius = 20;
series.tooltip.background.strokeOpacity = 0;
series.tooltip.pointerOrientation = "vertical";
series.tooltip.label.minWidth = 40;
series.tooltip.label.minHeight = 40;
series.tooltip.label.textAlign = "middle";
series.tooltip.label.textValign = "middle";

// Make bullets grow on hover
var bullet = series.bullets.push(new am4charts.CircleBullet());
bullet.circle.strokeWidth = 2;
bullet.circle.radius = 4;
bullet.circle.fill = am4core.color("#fff");

var bullethover = bullet.states.create("hover");
bullethover.properties.scale = 1.3;

// Make a panning cursor
chart.cursor = new am4charts.XYCursor();
chart.cursor.behavior = "panXY";
chart.cursor.xAxis = dateAxis;
chart.cursor.snapToSeries = series;

// Create vertical scrollbar and place it before the value axis
chart.scrollbarY = new am4core.Scrollbar();
chart.scrollbarY.parent = chart.leftAxesContainer;
chart.scrollbarY.toBack();

// Create a horizontal scrollbar with previe and place it underneath the date axis
chart.scrollbarX = new am4charts.XYChartScrollbar();
chart.scrollbarX.series.push(series);
chart.scrollbarX.parent = chart.bottomAxesContainer;

chart.events.on("ready", function () {
  dateAxis.zoom({start:1-7/termDate, end:1});
});

}); // end am4core.ready()
</script>

<!-- HTML -->
<div id="chartdiv"></div>
```



#完成!!
[![Image from Gyazo](https://i.gyazo.com/12ddfefc7e8b6d2696c1d39d8e909f88.gif)](https://gyazo.com/12ddfefc7e8b6d2696c1d39d8e909f88)
Jul22~Jul28の直近の1週間が表示されてますね。

##参考文献
[Railsにて不連続な間隔(日付など)で投稿された値をamChartsを使って折れ線グラフを作成する。](https://qiita.com/pdmmcsfcs/items/95e06be830404e1230cb)