[JAVA] [Rails] Creation of the second vertical axis and Japanese localization in graph drawing using amCharts4, etc.

Introduction

In this article, we will use amChart, a JavaScript graph drawing library, to share how to create a second vertical axis when implementing a multi-axis line graph and how to customize it into Japanese.

Development environment

Ruby 2.5.1 Rails 5.2.4.4

What is amCharts?

amCharts is a javascript graph drawing library that can draw various kinds of high-performance graphs.

Official reference: https://www.amcharts.com/docs/v4/

Since there is little information in Japanese, we recommend that you refer to the official reference when customizing.

Complete image

Currently, we are developing an app that has a function to record and graph weight and body fat percentage. I used amCharts4 to draw the date on the horizontal axis, the weight on the first vertical axis, and the body fat percentage on the second vertical axis on one graph.

The graph below is the completed image. ezgif-6-ef32c8681700.gif

Implementation procedure / explanation

Introduction of amCharts

Please refer to this article for how to install amCharts. Create a graph using amcharts 4 Demos

Creating a graph when the values on the horizontal axis are discontinuous

For creating the graph when the values on the horizontal axis of this article are discontinuous, I referred to the following article. Create a line graph using amCharts for values posted in Rails at discontinuous intervals (dates, etc.).

Preparation of demo data

Seed the csv file and prepare the following demo data.

id date weight body_fat_percentage
1 2020/06/08 72 15
2 ・ ・ ・ ・ ・ ・ ・ ・ ・

Completed sample code

I will paste the sample code before the explanation. The description on the Rails side is omitted this time.

record.html.erb
<style>
  #chartdiv {
    width: 700px;
    height: 300px;
  }
</style>

//Load the required JS file
<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>
<script src="//www.amcharts.com/lib/4/lang/ja_JP.js"></script>

<script>
am4core.ready(function() {

am4core.useTheme(am4themes_animated);

var chart = am4core.create("chartdiv", am4charts.XYChart);
chart.dateFormatter.language = new am4core.Language();
chart.dateFormatter.language.locale = am4lang_ja_JP;
chart.language.locale["_date_day"] = "MMMdd day";
chart.language.locale["_date_year"] = "yyyy year";

const weights = <%== JSON.dump(@weights) %>;
const body_fat_percentages = <%== JSON.dump(@body_fat_percentages) %>;
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

function generateChartData() {
  var chartData = [];
  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);
      if ((new Date(dates[j])) - (newDate) == 0 ){
        weight = weights[j]
        body_fat_percentage = body_fat_percentages[j]
        chartData.push({
          date1: newDate,
          weight: weight,
          date2: newDate,
          body_fat_percentage: body_fat_percentage
        });
      }
    }
  }
  return chartData;
}

chart.data = generateChartData();

//Graph title settings
var title = chart.titles.create();
title.text = "Changes in body weight and body fat percentage"; //Graph title settings
title.fontSize = 15; //Setting the font size of the graph title
//Tooltip display content settings to be displayed when the title is hovered with the mouse
title.tooltipText = "You can zoom in with the scroll bar."; 

//Setting of the first horizontal axis
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
dateAxis.renderer.labels.template.fill = am4core.color("#ffffff");

//2nd horizontal axis setting
var dateAxis2 = chart.xAxes.push(new am4charts.DateAxis());
dateAxis2.tooltip.disabled = true; //Tooltip hiding settings
dateAxis2.renderer.grid.template.location = 0;
dateAxis2.renderer.labels.template.fill = am4core.color("#000000");

//Setting of the first vertical axis
var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis.tooltip.disabled = true;
valueAxis.renderer.labels.template.fill = am4core.color("#e59165");
valueAxis.renderer.minWidth = 60;
valueAxis.renderer.labels.template.adapter.add("text", function(text) {
  return text + "kg";
});
valueAxis.renderer.fontWeight = "bold"; //Change axis value to bold

//Setting of the second vertical axis
var valueAxis2 = chart.yAxes.push(new am4charts.ValueAxis());
valueAxis2.tooltip.disabled = true;
valueAxis2.renderer.grid.template.strokeDasharray = "2,3";
valueAxis2.renderer.labels.template.fill = am4core.color("#dfcc64");
valueAxis2.renderer.minWidth = 60;
valueAxis2.renderer.labels.template.adapter.add("text", function(text) {
  return text + "%";
});
valueAxis2.renderer.opposite = true; //Set the second vertical axis to the right
valueAxis2.renderer.fontWeight = "bold"; //Change axis value to bold

//Setting the value for the first vertical axis
var series = chart.series.push(new am4charts.LineSeries());
series.name = "body weight";
series.dataFields.dateX = "date1";
series.dataFields.valueY = "weight";
series.tooltipText = "{valueY.value}kg";
series.fill = am4core.color("#e59165");
series.stroke = am4core.color("#e59165");
series.smoothing = "monotoneX";
series.strokeWidth = 2;

//Setting points of the series(1st vertical axis)
var bullet = series.bullets.push(new am4charts.Bullet());
var circle = bullet.createChild(am4core.Circle);
circle.width = 5;
circle.height = 5;
circle.horizontalCenter = "middle";
circle.verticalCenter = "middle";

//Setting the value for the first vertical axis
var series2 = chart.series.push(new am4charts.LineSeries());
series2.name = "body fat percentage";
series2.dataFields.dateX = "date2";
series2.dataFields.valueY = "body_fat_percentage";
series2.yAxis = valueAxis2;
series2.xAxis = dateAxis2;
series2.tooltipText = "{valueY.value}%"; //Tooltip display settings
series2.fill = am4core.color("#dfcc64"); //Tooltip color
series2.stroke = am4core.color("#dfcc64"); //Graph line color
series2.smoothing = "monotoneX";
series2.strokeWidth = 2;

//Setting points of the series(2nd vertical axis)
var bullet2 = series2.bullets.push(new am4charts.Bullet());
var circle2 = bullet2.createChild(am4core.Circle);
circle2.width = 5;
circle2.height = 5;
circle2.horizontalCenter = "middle";
circle2.verticalCenter = "middle";

chart.scrollbarX = new am4core.Scrollbar(); //Scrollbar settings

//Cursor settings
chart.cursor = new am4charts.XYCursor();
chart.cursor.xAxis = dateAxis2;

//Legend settings
chart.legend = new am4charts.Legend();
chart.legend.parent = chart.plotContainer;
chart.legend.zIndex = 100;
chart.legend.position = "top";
chart.legend.contentAlign = "right";

//Grid line settings
valueAxis2.renderer.grid.template.strokeOpacity = 0.07;
dateAxis2.renderer.grid.template.strokeOpacity = 0.07;
dateAxis.renderer.grid.template.strokeOpacity = 0.07;
valueAxis.renderer.grid.template.strokeOpacity = 0.07;

});
</script>

<div id="chartdiv"></div>

Commentary

Setting of multiple vertical axes

As shown in the sample code, in the case of a multi-axis graph, it is necessary to set each axis and each value. Make settings such as the data to be used for each.

Localizing into Japanese

If the horizontal axis is a date, the default notation is American, so it will be in English as shown in the figure below. スクリーンショット 2020-10-25 22.02.52.png

There is no problem as it is, but if you want to write "◯ month ◯ day", add the following settings. With the standard translation settings, for example, "Aug" can be translated to "August", but the number of days is not translated as "XX days", so add your own rules as follows. You can do the same for the year.

<script src="//www.amcharts.com/lib/4/lang/ja_JP.js"></script> //Call the locale file
<script>
//Omission
chart.dateFormatter.language = new am4core.Language(); //Standard translation settings
chart.dateFormatter.language.locale = am4lang_ja_JP; //Standard translation settings
chart.language.locale["_date_day"] = "MMMdd day";Overwrite with your own rules
chart.language.locale["_date_year"] = "yyyy year";Overwrite with your own rules
//Omission
</script>

[Reference link]  https://www.amcharts.com/docs/v4/concepts/locales/  https://github.com/amcharts/amcharts4/blob/master/src/lang/ja_JP.ts

Setting of the second vertical axis

With the default settings, both the first vertical axis and the second vertical axis are on the left side. スクリーンショット 2020-10-25 22.14.34.png It's a little hard to see, so if you want to change the second vertical axis to the right, add the following settings.

valueAxis2.renderer.opposite = true; //Set the second vertical axis to the right

Introducing other additional settings

Data points can be set for each series. You can change it to a square by changing circle to square.

var bullet = series.bullets.push(new am4charts.Bullet());
var circle = bullet.createChild(am4core.Circle);
circle.width = 5;
circle.height = 5;
circle.horizontalCenter = "middle";
circle.verticalCenter = "middle";

[Reference link]  https://www.amcharts.com/docs/v4/concepts/bullets/

series.smoothing = "monotoneX";
series2.fill = am4core.color("#dfcc64"); //Tooltip color
series2.stroke = am4core.color("#dfcc64"); //Graph line color

Summary

You can use amCharts to draw high-performance graphs. You can create various graphs other than line graphs. There is not much information in Japanese, so if you want to customize it, we recommend that you refer to the official reference.

Reference URL

Create a graph using amcharts 4 Demos Create a line graph using amCharts for values posted in Rails at discontinuous intervals (dates, etc.).

Recommended Posts

[Rails] Creation of the second vertical axis and Japanese localization in graph drawing using amCharts4, etc.
Extend Highfaces to flip the vertical axis of the graph
[Rails] How to display the weather forecast of the registered address in Japanese using OpenWeatherMap
[Rails] Japanese localization of error message when using Form object
[Rails] Japanese localization using rails-i18n
[Rails] Japanese localization of error messages
[Rails] Validation settings and Japanese localization
Japanese localization of error messages (rails)
Calculate the percentage of "good", "normal", and "bad" in the questionnaire using SQL
Display Japanese calendar and days of the week using java8 standard class
The identity of params [: id] in rails
Japanese localization of CentOS 8 and Japanese keyboard layout