C3.jsのloadメソッドを中途半端なタイミングで呼ぶとアニメーションが止まるので避ける。
先日つくった :link: 自殺者数チャートがどうも使いづらい+比較しづらいと思っており、そんな時にC3.jsを見つけてアニメーション良いですねなどと言いながら作りなおしているときに気づきました。
消えるべき棒グラフが残留している図
対応
React
のprops
で降ってくるのをポンポンload
してアニメーション中に再描画しているのが原因でしたのでこれをどうにかします。
Promise
でアニメーション中のあらたなload
を避ける
private promice = Promise.resolve();
private chart; // C3.jsでgenerateされる
writeChart(){
... // 値の準備など
this.promice = this.promice.then((v)=> {
return new Promise((resolve, _)=> {
this.chart.load({columns, types, unload});
setTimeout(()=> resolve(), 500);
});
});
}
その他
完全に同値の場合再描画を避けるなどしました。
これは同じデータでもload
を呼ぶと一見アニメーションが起こっていないように見えても、内部でなにかが起こっているからです(その分遅延が必要になる)。
発生に関するあれこれ
中途半端なタイミングとは
大体、0.2秒ぐらいのタイミングでload
を使用して値を書き換えると起こります。
症状としては、上の図のような残留や、同カテゴリ内の棒グラフ間に隙間ができるなどです。
これはアニメーション「中」というのが重要で、ローカル上でapiを叩いている場合など間隙なくload
が連続して呼ばれる場合などにはわかりづらい現象です。
これはまったく同じデータがload
され、一見アニメーションが起こっていない場合でも問題がある再描画となります。
(おそらくですが、最初に発行されたアニメーションの停止命令が、後から発行されたアニメーションも全てとめてしまうのでしょう)
done
パラメーターが使えなくて残念だった
:link: C3.js | D3-based reusable chart library
done will be called after data loaded, but it's not after rendering. It's because rendering will finish after some transition and there is some time lag between loading and rendering.