0
Help us understand the problem. What are the problem?
Organization

FileMaker + amCharts で BarChartRace、試しに五大商社の株価推移を見る

はじめに

対象読者

  • FileMaker に興味がある人
  • BarChartRace を手軽に作りたい人
  • 次の前置きを要参照

前置き

環境

what is amCharts

  • 公式サイト
    • 以下 OG title だと amCharts 4 となっているけれど、現行の最新版は amCharts 5がリリースされたところです ( 2022/07 時点 )

  • グラフ/チャート系が充実した JavaScript ライブラリ
  • ロゴつきなら無料で使える

You can download and use all amCharts 5 products for free. The only limitation of the free version is that a small amCharts logo will be displayed in the corner of your charts.

what is BarChartRace

  • 次の項も参照

最終的に出来上がるモノ

  • 以下のような感じ

Image from Gyazo

下準備その1

ファイル作成

  • FileMaker-BarChartRace.fmp12

表示用テーブル作成

  • races

image.png

フィールド作成

  • id : 数字
  • g_for_webview : テキスト、グローバル

image.png

スクリプト作成

set_global_var.amcharts_tags

  • 今回挿入する amCharts のタグをグローバル変数として定義しておく

image.png

"<script src=\"https://cdn.amcharts.com/lib/5/index.js\"></script>" &&
"<script src=\"https://cdn.amcharts.com/lib/5/xy.js\"></script>" &&
"<script src=\"https://cdn.amcharts.com/lib/5/themes/Animated.js\"></script>"

set_global_var.style_tags

  • 今回挿入する CSS style のタグをグローバル変数として定義しておく

image.png

"<style>
#chartdiv {
  height: 500px;
  width: 100%;
}
</style>"

open

  • スクリプトトリガで OnLayoutEnter

image.png
image.png

レイアウト作成

レイアウト全体

  • 最低限以下のように配置

image.png

WEB ビューア

  • 以下のような計算式で
Let (
  [
    amcharts_tags = $$amcharts_tags;
    style_tags = $$style_tags;

    result = races::g_for_webview;
    result = Substitute ( result ; "[[[amcharts_tags]]]" ; amcharts_tags );
    result = Substitute ( result ; "[[[style_tags]]]" ; style_tags )
  ];

  result
)

g_for_webview への入力

  • HTML テンプレートを g_for_webview フィールドへ入力
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
</body>
</html>

デモからコードを転記して動作確認

転記

  • その際、以下の箇所は [[[style_tags]]][[[amcharts_tags]]] とに書き換えておく
    • グローバル変数を呼び出すため
<!-- Styles -->
<style>
#chartdiv {
  width: 100%;
  height: 500px;
}
</style>

<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>
  • 長いけれどひとまず全部載せておく……
[[[style_tags]]]
[[[amcharts_tags]]]

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

// Data
var allData = {
  "2002": {
    "Friendster": 0,
    "Facebook": 0,
    "Flickr": 0,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 0,
    "Instagram": 0,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 0
  },
  "2003": {
    "Friendster": 4470000,
    "Facebook": 0,
    "Flickr": 0,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 0,
    "Instagram": 0,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 0
  },
  "2004": {
    "Friendster": 5970054,
    "Facebook": 0,
    "Flickr": 3675135,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 0,
    "Instagram": 0,
    "MySpace": 980036,
    "Orkut": 4900180,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 0
  },
  "2005": {
    "Friendster": 7459742,
    "Facebook": 0,
    "Flickr": 7399354,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 9731610,
    "Instagram": 0,
    "MySpace": 19490059,
    "Orkut": 9865805,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 1946322
  },
  "2006": {
    "Friendster": 8989854,
    "Facebook": 0,
    "Flickr": 14949270,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 19932360,
    "Instagram": 0,
    "MySpace": 54763260,
    "Orkut": 14966180,
    "Pinterest": 0,
    "Reddit": 248309,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 19878248
  },
  "2007": {
    "Friendster": 24253200,
    "Facebook": 0,
    "Flickr": 29299875,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 29533250,
    "Instagram": 0,
    "MySpace": 69299875,
    "Orkut": 26916562,
    "Pinterest": 0,
    "Reddit": 488331,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 143932250
  },
  "2008": {
    "Friendster": 51008911,
    "Facebook": 100000000,
    "Flickr": 30000000,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 55045618,
    "Instagram": 0,
    "MySpace": 72408233,
    "Orkut": 44357628,
    "Pinterest": 0,
    "Reddit": 1944940,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 294493950
  },
  "2009": {
    "Friendster": 28804331,
    "Facebook": 276000000,
    "Flickr": 41834525,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 57893524,
    "Instagram": 0,
    "MySpace": 70133095,
    "Orkut": 47366905,
    "Pinterest": 0,
    "Reddit": 3893524,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 413611440
  },
  "2010": {
    "Friendster": 0,
    "Facebook": 517750000,
    "Flickr": 54708063,
    "Google Buzz": 166029650,
    "Google+": 0,
    "Hi5": 59953290,
    "Instagram": 0,
    "MySpace": 68046710,
    "Orkut": 49941613,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 43250000,
    "WeChat": 0,
    "Weibo": 19532900,
    "Whatsapp": 0,
    "YouTube": 480551990
  },
  "2011": {
    "Friendster": 0,
    "Facebook": 766000000,
    "Flickr": 66954600,
    "Google Buzz": 170000000,
    "Google+": 0,
    "Hi5": 46610848,
    "Instagram": 0,
    "MySpace": 46003536,
    "Orkut": 47609080,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 92750000,
    "WeChat": 47818400,
    "Weibo": 48691040,
    "Whatsapp": 0,
    "YouTube": 642669824
  },
  "2012": {
    "Friendster": 0,
    "Facebook": 979750000,
    "Flickr": 79664888,
    "Google Buzz": 170000000,
    "Google+": 107319100,
    "Hi5": 0,
    "Instagram": 0,
    "MySpace": 0,
    "Orkut": 45067022,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 146890156,
    "Twitter": 160250000,
    "WeChat": 118123370,
    "Weibo": 79195730,
    "Whatsapp": 0,
    "YouTube": 844638200
  },
  "2013": {
    "Friendster": 0,
    "Facebook": 1170500000,
    "Flickr": 80000000,
    "Google Buzz": 170000000,
    "Google+": 205654700,
    "Hi5": 0,
    "Instagram": 117500000,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 293482050,
    "Twitter": 223675000,
    "WeChat": 196523760,
    "Weibo": 118261880,
    "Whatsapp": 300000000,
    "YouTube": 1065223075
  },
  "2014": {
    "Friendster": 0,
    "Facebook": 1334000000,
    "Flickr": 0,
    "Google Buzz": 170000000,
    "Google+": 254859015,
    "Hi5": 0,
    "Instagram": 250000000,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 0,
    "Reddit": 135786956,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 388721163,
    "Twitter": 223675000,
    "WeChat": 444232415,
    "Weibo": 154890345,
    "Whatsapp": 498750000,
    "YouTube": 1249451725
  },
  "2015": {
    "Friendster": 0,
    "Facebook": 1516750000,
    "Flickr": 0,
    "Google Buzz": 170000000,
    "Google+": 298950015,
    "Hi5": 0,
    "Instagram": 400000000,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 0,
    "Reddit": 163346676,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 475923363,
    "Twitter": 304500000,
    "WeChat": 660843407,
    "Weibo": 208716685,
    "Whatsapp": 800000000,
    "YouTube": 1328133360
  },
  "2016": {
    "Friendster": 0,
    "Facebook": 1753500000,
    "Flickr": 0,
    "Google Buzz": 0,
    "Google+": 398648000,
    "Hi5": 0,
    "Instagram": 550000000,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 143250000,
    "Reddit": 238972480,
    "Snapchat": 238648000,
    "TikTok": 0,
    "Tumblr": 565796720,
    "Twitter": 314500000,
    "WeChat": 847512320,
    "Weibo": 281026560,
    "Whatsapp": 1000000000,
    "YouTube": 1399053600
  },
  "2017": {
    "Friendster": 0,
    "Facebook": 2035750000,
    "Flickr": 0,
    "Google Buzz": 0,
    "Google+": 495657000,
    "Hi5": 0,
    "Instagram": 750000000,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 195000000,
    "Reddit": 297394200,
    "Snapchat": 0,
    "TikTok": 239142500,
    "Tumblr": 593783960,
    "Twitter": 328250000,
    "WeChat": 921742750,
    "Weibo": 357569030,
    "Whatsapp": 1333333333,
    "YouTube": 1495657000
  },
  "2018": {
    "Friendster": 0,
    "Facebook": 2255250000,
    "Flickr": 0,
    "Google Buzz": 0,
    "Google+": 430000000,
    "Hi5": 0,
    "Instagram": 1000000000,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 246500000,
    "Reddit": 355000000,
    "Snapchat": 0,
    "TikTok": 500000000,
    "Tumblr": 624000000,
    "Twitter": 329500000,
    "WeChat": 1000000000,
    "Weibo": 431000000,
    "Whatsapp": 1433333333,
    "YouTube": 1900000000
  }
};


// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");

root.numberFormatter.setAll({
  numberFormat: "#a",

  // Group only into M (millions), and B (billions)
  bigNumberPrefixes: [
    { number: 1e6, suffix: "M" },
    { number: 1e9, suffix: "B" }
  ],

  // Do not use small number prefixes at all
  smallNumberPrefixes: []
});

var stepDuration = 2000;


// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([am5themes_Animated.new(root)]);


// Create chart
// https://www.amcharts.com/docs/v5/charts/xy-chart/
var chart = root.container.children.push(am5xy.XYChart.new(root, {
  panX: true,
  panY: true,
  wheelX: "none",
  wheelY: "none"
}));


// We don't want zoom-out button to appear while animating, so we hide it at all
chart.zoomOutButton.set("forceHidden", true);


// Create axes
// https://www.amcharts.com/docs/v5/charts/xy-chart/axes/
var yRenderer = am5xy.AxisRendererY.new(root, {
  minGridDistance: 20,
  inversed: true
});
// hide grid
yRenderer.grid.template.set("visible", false);

var yAxis = chart.yAxes.push(am5xy.CategoryAxis.new(root, {
  maxDeviation: 0,
  categoryField: "network",
  renderer: yRenderer
}));

var xAxis = chart.xAxes.push(am5xy.ValueAxis.new(root, {
  maxDeviation: 0,
  min: 0,
  strictMinMax: true,
  extraMax: 0.1,
  renderer: am5xy.AxisRendererX.new(root, {})
}));

xAxis.set("interpolationDuration", stepDuration / 10);
xAxis.set("interpolationEasing", am5.ease.linear);


// Add series
// https://www.amcharts.com/docs/v5/charts/xy-chart/series/
var series = chart.series.push(am5xy.ColumnSeries.new(root, {
  xAxis: xAxis,
  yAxis: yAxis,
  valueXField: "value",
  categoryYField: "network"
}));

// Rounded corners for columns
series.columns.template.setAll({ cornerRadiusBR: 5, cornerRadiusTR: 5 });

// Make each column to be of a different color
series.columns.template.adapters.add("fill", function (fill, target) {
  return chart.get("colors").getIndex(series.columns.indexOf(target));
});

series.columns.template.adapters.add("stroke", function (stroke, target) {
  return chart.get("colors").getIndex(series.columns.indexOf(target));
});

// Add label bullet
series.bullets.push(function () {
  return am5.Bullet.new(root, {
    locationX: 1,
    sprite: am5.Label.new(root, {
      text: "{valueXWorking.formatNumber('#.# a')}",
      fill: root.interfaceColors.get("alternativeText"),
      centerX: am5.p100,
      centerY: am5.p50,
      populateText: true
    })
  });
});

var label = chart.plotContainer.children.push(am5.Label.new(root, {
  text: "2002",
  fontSize: "8em",
  opacity: 0.2,
  x: am5.p100,
  y: am5.p100,
  centerY: am5.p100,
  centerX: am5.p100
}));

// Get series item by category
function getSeriesItem(category) {
  for (var i = 0; i < series.dataItems.length; i++) {
    var dataItem = series.dataItems[i];
    if (dataItem.get("categoryY") == category) {
      return dataItem;
    }
  }
}

// Axis sorting
function sortCategoryAxis() {
  // sort by value
  series.dataItems.sort(function (x, y) {
    return y.get("valueX") - x.get("valueX"); // descending
    //return x.get("valueX") - y.get("valueX"); // ascending
  });

  // go through each axis item
  am5.array.each(yAxis.dataItems, function (dataItem) {
    // get corresponding series item
    var seriesDataItem = getSeriesItem(dataItem.get("category"));

    if (seriesDataItem) {
      // get index of series data item
      var index = series.dataItems.indexOf(seriesDataItem);
      // calculate delta position
      var deltaPosition =
        (index - dataItem.get("index", 0)) / series.dataItems.length;
      // set index to be the same as series data item index
      if (dataItem.get("index") != index) {
        dataItem.set("index", index);
        // set deltaPosition instanlty
        dataItem.set("deltaPosition", -deltaPosition);
        // animate delta position to 0
        dataItem.animate({
          key: "deltaPosition",
          to: 0,
          duration: stepDuration / 2,
          easing: am5.ease.out(am5.ease.cubic)
        });
      }
    }
  });
  // sort axis items by index.
  // This changes the order instantly, but as deltaPosition is set, they keep in the same places and then animate to true positions.
  yAxis.dataItems.sort(function (x, y) {
    return x.get("index") - y.get("index");
  });
}

var year = 2002;

// update data with values each 1.5 sec
var interval = setInterval(function () {
  year++;

  if (year > 2018) {
    clearInterval(interval);
    clearInterval(sortInterval);
  }

  updateData();
}, stepDuration);

var sortInterval = setInterval(function () {
  sortCategoryAxis();
}, 100);

function setInitialData() {
  var d = allData[year];

  for (var n in d) {
    series.data.push({ network: n, value: d[n] });
    yAxis.data.push({ network: n });
  }
}

function updateData() {
  var itemsWithNonZero = 0;

  if (allData[year]) {
    label.set("text", year.toString());

    am5.array.each(series.dataItems, function (dataItem) {
      var category = dataItem.get("categoryY");
      var value = allData[year][category];

      if (value > 0) {
        itemsWithNonZero++;
      }

      dataItem.animate({
        key: "valueX",
        to: value,
        duration: stepDuration,
        easing: am5.ease.linear
      });
      dataItem.animate({
        key: "valueXWorking",
        to: value,
        duration: stepDuration,
        easing: am5.ease.linear
      });
    });

    yAxis.zoom(0, itemsWithNonZero / yAxis.dataItems.length);
  }
}

setInitialData();
setTimeout(function () {
  year++;
  updateData();
}, 50);

// Make stuff animate on load
// https://www.amcharts.com/docs/v5/concepts/animations/
series.appear(1000);
chart.appear(1000, 100);

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

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

動作確認

  • ここまでで、ひとまず以下のようなアニメーションがされればヨシ
    • GIF アニメーションでちょっともっさりした見え方になってますが、実動はもっと高速です

Image from Gyazo

下準備その2

表示したいデータを決める

  • さて、ここまではデモ用のコード内に直書きされていたデータでの動作確認でした。次は、実際の FileMaker テーブル内にあるデータで動作させられるように進めます
  • 表示させたいデータ用のテーブルを作りましょう。今回は既にクロス集計されたデータを使い、レコードの区分けは によるものとして、それ以外はフィールドで区切るようにします
  • じゃあ何のデータを表示させようかということで、今回は、日本の五大商社の年末株価(終値)の推移でも見てみましょう

FileMaker データ用のテーブルを作成

  • 今回は年毎に区切るということで annal_reports というテーブル名にしておきます

image.png

フィールド作成

  • id : 数字
  • year : 数字
  • その他、乱暴にも各商社名をそのままフィールド名とします。全部数字で
    • これができるのが FileMaker の驚きなところでもあり良いところでもあり

image.png

ダミーデータ準備

  • ちょっと面倒なのですが、先ほど貼った以下の各ページから、各年の 終値(円) の値を取ってきて csv データにします(手動でがんばる)
    • 何かもっと良いデータ提供サイトあったら教えてください……

"year", "伊藤忠商事", "丸紅", "三井物産", "住友商事", "三菱商事"
2013, 1299, 756, 1465, 1321, 2017
2014, 1292, 724.7, 1621.5, 1242, 2217
2015, 1442, 625.1, 1445.5, 1240.5, 2028
2016, 1552, 662.8, 1607, 1375.5, 2490
2017, 2103, 816.1, 1832, 1915, 3113
2018, 1867, 772.4, 1690.5, 1561.5, 3020
2019, 2534.5, 810.6, 1946, 1624, 2900
2020, 2964, 686.1, 1889.5, 1365.5, 2541
2021, 3518, 1119.5, 2723.5, 1700.5, 3652

ダミーデータ投下

  • 上記 csv データをインポート
    • 上記、見やすくするために半角スペースなど入れていますが、消してからインポートしないと半角スペースごと取り込まれてしまうという問題に遭遇します、FileMaker さん……

image.png

  • csv でやるとヘッダ行までインポートされるので不要レコード削除……

image.png

  • 以下のようにレコードが揃っていればヨシ

image.png

データ表示部分の形式を確認

  • amCharts のデモから転記してきたコード内に、データ部分が含まれているので、そこでどのような形式を要求されているのか確認
  • 以下のように year の中に各項目と値が記述されている
  "2002": {
    "Friendster": 0,
    "Facebook": 0,
    "Flickr": 0,
    "Google Buzz": 0,
    "Google+": 0,
    "Hi5": 0,
    "Instagram": 0,
    "MySpace": 0,
    "Orkut": 0,
    "Pinterest": 0,
    "Reddit": 0,
    "Snapchat": 0,
    "TikTok": 0,
    "Tumblr": 0,
    "Twitter": 0,
    "WeChat": 0,
    "Weibo": 0,
    "Whatsapp": 0,
    "YouTube": 0
  },
  "2003": {
    // 以下略
  • よって、以下のようなものが出力されるとヨシ
  "2013": {
    "伊藤忠商事": 1299,
    "丸紅": 756,
    "三井物産": 1465,
    "住友商事": 1321,
    "三菱商事": 2017
  },
  "2014": {
  // 以下略

レイアウトと計算フィールド作成

レイアウト

  • for_json という軽量簡潔なレイアウトを用意しておく

image.png

計算フィールド

  • c_json という名の、以下のような計算フィールドを作成
While (
  [ 
    fileName = Get ( ファイル名 );
    layoutName = "for_json";
    fields = FieldNames ( fileName ; layoutName);
    fields = Substitute ( fields ; "year" ; "" );
    fields = Substitute ( fields ; "c_json" ; "" );
    fieldsCount = ValueCount ( fields ); 
    i = 0;
    result = ""
  ];

  i < fieldsCount;

  [
    i = i + 1;
    name = GetValue ( fields ; i );
    value = GetField ( name );
    fieldType = FieldType ( fileName ; name ); 
    jsonType = If (
                 PatternCount ( fieldType ; "Number");
                   JSONNumber;
                   JSONString
               );
    result = JSONSetElement ( result; name; value; jsonType )
  ];

  "\"" & year & "\": " & 
  JSONFormatElements ( result ) & ","
)

単一レコードの JSON データ確認

  • annual_reports レイアウトに c_json フィールドを設置してみて出力結果を確認

image.png

対象レコードの JSON データ化

リレーション作成

  • races テーブルを親にして any 条件でリレーションを作成
    • このあたり、type みたいなフィールドを racesannual_repots 両方に持たせてそれをキーにし、特定の条件のレポートだけに絞り込む、というやり方もアリ

image.png

計算フィールド作成

  • races テーブルにも c_json 計算フィールドを作成
List ( racesannual_reportsany::c_json )

出力確認

  • races レイアウトに c_json フィールドを設置してみて出力結果を確認

image.png

締め作業

g_for_webview の書き換え

  • ここまで来れば、もうあと一歩……

データ部分の書き換え

  • g_for_webview の以下箇所 allData = { より下の行からがデータにあたるので……

image.png

  • 以下のように書き換える
// Data
var allData = {
[[[c_json]]]
};

image.png

年情報の書き換え

  • サンプルコードの中では年情報が固定で直接書かれてしまっています
var label = chart.plotContainer.children.push(am5.Label.new(root, {
  text: "2002",
  fontSize: "8em",
  opacity: 0.2,
  x: am5.p100,
  y: am5.p100,
  centerY: am5.p100,
  centerX: am5.p100
}));

// 中略

var year = 2002;

// update data with values each 1.5 sec
var interval = setInterval(function () {
  year++;

  if (year > 2018) {
    clearInterval(interval);
    clearInterval(sortInterval);
  }

  updateData();
}, stepDuration);
  • 上記の 20022018 は動的に変わって欲しいので [[[start_year]]] [[[end_year]]] として、以下のように書き換えておきます
var label = chart.plotContainer.children.push(am5.Label.new(root, {
  text: "[[[start_year]]]",
  fontSize: "8em",
  opacity: 0.2,
  x: am5.p100,
  y: am5.p100,
  centerY: am5.p100,
  centerX: am5.p100
}));

// 中略

var year = [[[start_year]]];

// update data with values each 1.5 sec
var interval = setInterval(function () {
  year++;

  if (year > [[[end_year]]]) {
    clearInterval(interval);
    clearInterval(sortInterval);
  }

  updateData();
}, stepDuration);

前年データの投入

  • amCharts できれいに描画開始したい場合、開始年より一年前のレコードですべての値が 0 になっているものが用意されている方がよい様子

image.png

WEB ビューアの書き換え

  • 計算式を以下のように
Let (
  [
    amcharts_tags = $$amcharts_tags;
    style_tags = $$style_tags;

    json = races::c_json;

    start_year = Min ( racesannual_reportsany::year );
    end_year = Max ( racesannual_reportsany::year );


    result = races::g_for_webview;

    result = Substitute ( result ; "[[[amcharts_tags]]]" ; amcharts_tags );
    result = Substitute ( result ; "[[[style_tags]]]" ; style_tags );

    result = Substitute ( result ; "[[[json]]]" ; json );

    result = Substitute ( result ; "[[[start_year]]]" ; start_year );
    result = Substitute ( result ; "[[[end_year]]]" ; end_year )
  ];

  result
)

動作確認

  • 以下のようにアニメーションされればヨシ!
    • 実際に FileMaker Pro 上で動作させている場合はもっと高速にぬるぬる動きますよ

Image from Gyazo

おわりに

雑感

  • 長かった! 書くのに時間がかかった! ここまでお読みいただきありがとうございました🙏
  • amCharts については、この BarChartRace 以外にも色々なグラフ表現が充実しているので、便利に使えると思います。ただちょっと慣れないとサンプル読むのに時間がかかるかもしれません。他にもコレで実装例出してみて欲しい、など希望があればコメントください
  • FileMaker グラフとは

GitHub 公開リポジトリ

  • .fmp12 ファイルのダウンロードや DDR ( Database Design Report ) の確認ができるようになっています。issue や Pull-req も歓迎
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
0
Help us understand the problem. What are the problem?