C3.jsというチャート描画ライブラリのline-chartについての記事です。
##C3.jsとは
C3.jsはjavascriptでチャートを作成できるライブラリです。色々なチャートを描画することが出来るので大変便利です。今回はこの中のline-chartについてです。
##現象
C3.jsのline-chartをつかって300point位のデータを20本並べたline-chartを描くWebPageを作成していました。再現プログラムを切り出したので、下のサンプルプログラムのデータは乱数で生成しています。
MacのSafariやChromeでは問題なく動いていたのですが、同じページをiOSの端末からアクセスすると異常に動作が遅く、たまに落ちてしまう現象が発生しました。
最初はデータの転送量が多くて中々反応していないのかと考えたり、iOSのjavascriptで扱うにはデータが多すぎるのかと考えていたのですが、どうも違ったようです。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js" charset="utf-8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.18/c3.min.js"></script>
</head>
<body>
<div id="chart"></div>
</body>
<script>
const chartObj = {
bindto: '#chart',
size: { width: 1280, height: 600 },
point: { show: false },
tooltip: { show: false },
data: {
columns: [],
},
};
for(let i = 0; i < 20; i++) {
chartObj.data.columns[i] = ['data' + i];
for(let j = 0; j < 300; j++) {
let d = Math.random() * 100;
if(j == 0) {
chartObj.data.columns[i].push(d);
} else {
d = chartObj.data.columns[i][j] + (d / 10 - 5);
if(d < 0) d = 0;
if(d > 100) d = 100;
chartObj.data.columns[i].push(d);
}
}
}
c3.generate(chartObj);
</script>
</html>
##問題点
Safariのinspectorで中身を見てみたところ、c3.jsのチャートはsvgで描画されているようですので更にその中を見ていくと
<g class="c3-chart-lines">
の下に
<g class="c3-chart-line c3-target c3-target-data0">
から順に20本のlineがあります。
更にその中を見てみると
<g class=" c3-shapes c3-shapes-data0 c3-lines c3-lines-data0">
があり、こちらがline-chartの線を引いているデータです。
ここまでは全く問題ありません。
この次に出てくるのが
<g class=" c3-shapes c3-shapes-data0 c3-circles c3-circles-data0" style="cursor: pointer;">
なのですが、中身は
<circle class="c3-shape c3-shape-0 c3-circle c3-circle-0" r="2.5" cx="13" cy="467.5179823348915" style="fill: rgb(31, 119, 180); opacity: 0;">
がline-chartのポイントの分全て存在しています。
20x300=6000個のcircleを描画しているので重たいようでした。
勿論そんなにline-chartにpointを表示させると画面がbusyなので消す設定にしているのですが、point: { show: false },
がどこに効いているかというとopacity: 0;
の部分みたいです。
##解決策
結局のところ、画像などに比べてデータの量としては問題になる大きさではないのでcircleを描画させなければいいと考えて、下記のstyleをcssに追加しました。
.c3-circles {
display: none;
}
これでグラフのスクロールや描画がサクサクと動くようになりました。