シンプルに視覚化
Highchartsは、開発者があらゆるWebおよびモバイルプラットフォームにチャートを簡単に追加できるようにします。
Javascript、Angular、React、VueJS、iOS、R、.NET、Python、その他に対応しています。
Highcharts React Wrapper ダッシュボード
このチュートリアルでは、HighchartsとReactラッパーを使用してシンプルでインタラクティブなダッシュボードを作成する方法を紹介します。この記事は、すべてのレベルの開発者に適しています。 経験豊富な開発者にとっては、すばやく読める内容で、ReactまたはHighchartsのいずれかが初めての場合には役立つことでしょう。
備考Create React Appと Visual Studio Code IDEを使用してこのプロジェクトは構築されました。 この GithubリンクまたはCodesandboxからプロジェクトをダウンロードできます。必要に応じて、前回の投稿を参照して、ゼロからプロジェクトを作成する方法を確認してください。
以下のダッシュボードは、2001年から2015年までのアメリカ合衆国における純エネルギー発電量を視覚化しています。 ダッシュボードでは、化石燃料、水力エネルギー、バイオマス、再生可能エネルギーの4つのカテゴリで生産された主要なエネルギー源を比較することができます。 データは米国エネルギー情報局(EIA)から収集しました。
ダッシュボードを作成する際には、次のベストプラクティスに従いました。
- グラフから背景を分離します(つまり、各チャートウィジェットの境界を示すために色を使用します)。
- 凡例をグラフに近づけます。
- 複雑なグラフを避けます(1つのグラフに多くのデータを詰め込むのではなく、重要な情報を複数のグラフに分割します)。
- データを探索するためのツールを提供します(例:ズームインとフィルタリング)。
- レスポンシブデザインを考えます。
効果的なダッシュボードの作成方法については、以下の記事「6 Things to Consider Before Putting Charts Into a Dashboard」を確認してください。ここでは、上記で説明した各ポイントに関する詳細とデモが表示されます。ライブインタラクティブダッシュボードを確認するには、Codesandboxプロジェクトリンクをクリックするか、下の画像をクリックしてください。
それでは、ダッシュボードを作成する手順を説明しましょう。
THE ARCHITECTURE
まず、グローバル・アーキテクチャを見直すことから始めましょう。 アーキテクチャの計画は、コンポーネント間の接続を示すのに役立ち、またデータの流れも可視化します。 コードを書く前に、アーキテクチャのプランニングに時間をかけることを強くお勧めします。
このダッシュボードの主なアイデアは比較的シンプルです。ユーザーがUIを介して日付範囲を選択すると、 このアクションによってこの日付範囲からデータを取得するプロセスが起動し、エネルギー源別にデータが集計され、 その結果が化石燃料、水力発電エネルギー、バイオマス、再生可能エネルギーのいずれかに分類されます。 最後のステップは、4つのインタラクティブなドーナツチャート(各カテゴリー1つ)にデータを表示することです。 ちなみに、ドーナツチャートまたは円グラフは、一目で比較や構成を示すのに最適です。 コンパクトで理解しやすいため、ダッシュボードでよく使用されます。
次に考えることは、アイデアを小さなコンポーネントに分解して、各コンポーネントをコーディングし、 メンテナンスしやすくすることでした。 いくつかのスケッチと最適化の後、最終的に7つのコンポーネントに辿り着きました。
- データコンポーネント:EIAウェブサイトから収集したデータを保存
- データ処理: ユーザー選択後にデータを集計
- チャートテンプレート: Highchartsライブラリで必要なインタラクティブチャートの構成を設定
- 範囲選択コンポーネント: ユーザーが使用する日付セレクターを処理
- チャートモジュール: ユーザーによって選択された各範囲後にチャートをレンダリング
- ダッシュボードコンポーネント: すべてのチャットを1つのコンテナに収集してレンダリング
- アプリケーションコンポーネント: すべてのコンポーネントを収集してダッシュボードを実行
その後、プロジェクトを7つのコンポーネント、 4つのReactJSコンポーネント(紫)と3つのモジュール (緑)に分割しました。 基準はシンプルでした。何かをレンダリングする必要がある場合、そのコンポーネントはReactJSコンポーネントになります。 そうでなければ、レンダリングはなく、データ処理用のオブジェクトや関数がいくつかあるだけの標準的なJavaScriptモジュールです。
Highcharts React Wrapper (水色)をアーキテクチャに追加して、プロジェクトにライブラリを追加する場所を知るために可視化する必要がありました。そして、チャートのレンダリングがチャートコンポーネントで行われるため、Highcharts React Wrapperをそのコンポーネントにインポートしました。
コーディング
アーキテクチャを設定した後、Create React Appを使用して新しいプロジェクトを作成しました。 その後、コンポーネントフォルダを追加し、各コンポーネント用のファイルを作成しました。 ReactJSコンポーネントを他のモジュールから分離するために、各ReactJSコンポーネントファイルの最初の文字を大文字にしました。 これは、インポートが直感的であるため、どのファイルが何を行っているかをすばやく認識するための良い方法であり、 ファイル間の曖昧さを減らすことができます。
プロジェクトのファイル構成を下記のように確認します:
それぞれのコンポーネントを深く掘り下げてみましょう:
データモジュールにはオブジェクトdataがあり、 各エネルギー源に関するデータを1つの専用オブジェクトに格納し、 export default dataを使ってオブジェクトdataをエクスポートします。
const data = { coal: { 2001: 1903955, ... }, pliquids: { 2001: 114646, ... }, pcoke: { 2001: 10235, ... }, ngas: { 2001: 639129, ... }, ogas: { 2001: 9040, ... }, nuclear: { 2001: 768825, ... }, chydroelectric: { 2001: 216962, ... }, wind: { 2001: 6737, ..., 2015: 93876 }, solar: { 2001: 543, ... }, geothermal: { 2001: 13740, ... }, biomass: { 2001: 49749, ... }, wood: { 2001: 35199, ... }, otherbio: { 2001: 14549, ... } }; export default data;
このモジュールは、データモジュールからデータをインポートし、 yearFromとyearToをパラメータとして使用して、 dataProcessingというアロー関数にデータを渡します。
import data from './data'; let dataProcessing = (yearFrom, yearTo) => { ...
この機能は、各エネルギー源について、日付範囲内に生産されたエネルギー量を計算するものです。
if (yearFrom < yearTo) { let coal = 0, pliquids = 0, pcoke = 0, ngas = 0, ogas = 0, nuclear = 0, chydroelectric = 0, wind = 0, solar = 0, geothermal = 0, biomass = 0, wood = 0, otherbio = 0; for (let i = yearFrom; i < yearTo; i++) { coal += data.coal[i]; pliquids += data.pliquids[i]; pcoke += data.pcoke[i]; ngas += data.ngas[i]; ogas += data.ogas[i]; nuclear += data.nuclear[i]; chydroelectric += data.chydroelectric[i]; wind += data.wind[i]; solar += data.solar[i]; geothermal += data.geothermal[i]; biomass += data.biomass[i]; wood += data.wood[i]; otherbio += data.otherbio[i]; }
算出されたデータは、エネルギー源の性質に応じた4つのオブジェクトに保存されます。:
fossilFuelData = [ { name: 'coal', y: coal }, { name: 'Petroleum Liquids', y: pliquids }, { name: 'Petroleum Coke', y: pcoke }, { name: 'Natural gas', y: ngas }, { name: 'Other Gases', y: ogas } ]; hydroElectricData = [ { name: 'Nuclear', y: nuclear }, { name: 'Conventional Hydroelectric', y: chydroelectric } ]; biomassData = [ { name: 'Biomass', y: biomass }, { name: 'Wood', y: wood }, { name: 'Otherbio', y: otherbio } ]; renewableEnergyData = [ { name: 'Wind', y: wind }, { name: 'Solar', y: solar }, { name: 'Geothermal', y: geothermal } ];
また、この関数は、ユーザーに範囲を選択するように指示するメッセージと、 yearFromがyearToより常に小さいか等しいことを確認するメッセージを処理します。
ダッシュボードには4つのインタラクティブなドーナツチャートがあります。 それぞれのチャートを個別に作成する代わりに、Highchartsライブラリ構造に従って1つのテンプレートモジュールを設定し、 Appモジュールで使用してチャートを作成します。
const template = { userConfig: { tooltip: { pointFormat: "{point.y} thousand megawatthours" }, plotOptions: { pie: { showInLegend: true, innerSize: "60%", dataLabels: { enabled: false, distance: -14, color: "white", style: { fontweight: "bold", fontsize: 50 } } } } }, yearFrom: "2001", yearTo: "2015", msg: "Select the range" }; export default template;
ご覧のとおり、テンプレートには、tooltipやplotOptionsなど、 主要な標準Highchartチャートの構成が含まれています。
このファイルはReactJSコンポーネントであり、ユーザーが日付範囲を選択できるようにするセレクト要素をレンダリングします。
このコンポーネントでは、Bootstrapを使用して要素のスタイルを決めています。 独自のスタイルを考えることもできますが、ここでは標準のスタイルライブラリを使用することにしました。
Chart.jsファイルは、別のReactJSコンポーネントであり、 更新があるたびにチャートをレンダリングします。
このコンポーネントのキー要素は、componentDidUpdate(prevProps、prevState) メソッドです。新しいチャートのパラメータを取得する前に更新があるかどうかを確認し、 それらのパラメータをChart stateコンポーネントに渡します。
componentDidUpdate(prevProps, prevState) { if (this.props.data !== prevProps.data) { this.setState({ chartData: { ...this.state.chartData, subtitle: { text: ( this.props.data.reduce((accumulator, obj) => accumulator + obj.y,0) / 1000).toFixed(2) + " TWh" }, series: [ { data: this.props.data } ] } }); } }
このコンポーネントでは、次のコードを使用してすべてのチャートを動的にレンダリングします。:
{this.props.charts && this.props.charts.map(chart => { return ( <div className="col-xs-12 col-sm-6 mb-2" key={i}> <Chart data={chart.serie} userConfig={this.props.userConfig} titleName={chart.title} /> </div> ); })}
最後に、このメインコンポーネントApp.jsですべてのReactJSコンポーネントを収集して、 全体のダッシュボードをレンダリングします
このコンポーネントには、アロー関数handleChangeYearがあります。
handleChangeYear = e => { this.setState({ [e.target.name]: e.target.value }); };
この関数は、セレクト要素のイベントを処理し、新しい時間範囲をコンポーネント App.jsの状態に保存します。このプロセスにより、 componentDidUpdate(prevProps、prevState)メソッドがトリガーされます。
componentDidUpdate(prevProps, prevState) { if (prevState.yearFrom !== this.state.yearFrom) { this.handleChangeSelect(); } if (prevState.yearTo !== this.state.yearTo) { this.handleChangeSelect(); } }
コンポーネント componentDidUpdate(prevProps, prevState)は、 handleChangeSelect()を呼び出して(データ処理モジュールで)データを処理し、 チャートを更新します。 このプロセス全体の最後のステップは、ダッシュボードに新しいチャートを表示することです。
App.jsファイルでは、Bootstrapを使って、 ダッシュボードに表示されるさまざまな要素のスタイルも決めています。
プロジェクトが終わってみて、最も難しく、最も時間がかかったのは、アーキテクチャを理解することで、 それ以降のコードの部分は簡単でした。 また、handleChangeYearについては、正しいボタンを処理していることを確認するために、 ブラケット記法を使用する必要がありました。