React、D3、およびそれらのエコシステムをまとめる
公開: 2022-03-102011年の作成以来、D3.jsは、Web上で複雑なデータ視覚化を構築するための事実上の標準になりました。 Reactは、コンポーネントベースのユーザーインターフェイスを作成するための最適なライブラリとしても急速に成熟しています。
ReactとD3はどちらも、時々衝突する目標を持って設計された2つの優れたツールです。 どちらもユーザーインターフェイス要素を制御し、さまざまな方法で制御します。 現在のプロジェクトに応じて明確な利点を最適化しながら、どのようにそれらを連携させることができますか?
この投稿では、D3の強力なチャート作成機能を必要とするReactプロジェクトの構築にどのように取り組むことができるかを見ていきます。 さまざまなテクニックと、メインの作業およびサイドプロジェクトでのニーズに最適なライブラリを選択する方法を発見します。
D3とDOM
D3.jsのD3は、データ駆動型ドキュメントを表します。 D3.jsは、インタラクティブな視覚化を作成するために必要なビルディングブロックを提供する低レベルのライブラリです。 SVG、HTML、キャンバス、CSSなどのWeb標準を使用して、広大なAPIを備えたフロントエンドツールボックスを組み立て、視覚化の外観と動作をほぼ無制限に制御します。 また、ユーザーが複雑なSVGパスを計算するのに役立ついくつかの数学関数も提供します。
それはどのように機能しますか?
一言で言えば、D3.jsはデータをロードしてDOMにアタッチします。 次に、そのデータをDOM要素にバインドし、それらの要素を変換して、必要に応じて状態間を遷移します。
D3.jsの選択は、SVGの複雑さに対処するのに役立つため、jQueryオブジェクトに似ています。 これが行われる方法は、jQueryがHTMLDOM要素を処理する方法に匹敵します。 どちらのライブラリも、同様のチェーンベースのAPIと、データストレージとしてのDOMの使用を共有しています。
データ結合
MikeBostocksの記事「ThinkingwithJoins」で説明されているように、データ結合は、D3が選択を使用してデータをDOM要素にリンクするプロセスです。
データ結合は、提供するデータを既に作成された要素と照合し、欠落しているアイテムを追加し、不要になった要素を削除するのに役立ちます。 D3.jsの選択を使用します。これは、データと組み合わせると、選択した要素を3つの異なるグループに分割します。作成する必要のある要素(入力グループ)、更新する必要のある要素(更新グループ)、および必要な要素です。削除されます(出口グループ)。
実際には、2つの配列を持つJavaScriptオブジェクトは、データ結合を表します。 選択範囲のenterメソッドとexitメソッドを呼び出すことで、enterグループとexitグループの操作をトリガーできますが、最新バージョンのD3.jsでは更新グループを直接操作できます。
Bostockが説明しているように、データ結合を使用すると、「リアルタイムデータを視覚化し、インタラクティブな探索を可能にし、データセット間をスムーズに移行できます」。 次のセクションで説明するように、これらは事実上、Reactが子要素のレンダリングを管理する方法と同様のdiffアルゴリズムです。
D3ライブラリ
D3コミュニティは、D3コードからコンポーネントを作成する標準的な方法を見つけていません。これは、D3.jsが非常に低レベルであるため、頻繁に必要になります。 カプセル化パターンはD3ベースのライブラリとほぼ同じ数であると言えますが、APIを使用して、オブジェクト指向、宣言型、機能型、連鎖型(またはD3型)の4つのグループに分類します。
私はD3.jsエコシステムについていくつかの調査を行い、小さくて高品質のサブセットを選択しました。 これらは、D3.jsバージョン4を備え、テストカバレッジが良好な最新のライブラリです。 APIのタイプと、抽象化の粒度が異なります。
プロット可能
Plottableは、粒度の低い機能を備えた、人気のあるオブジェクト指向のグラフ作成ライブラリです。 したがって、チャートを作成するには、軸、スケール、およびプロットを手動で設定する必要があります。 ここに例があります。
ビルボード
Billboardは、有名なC3.jsライブラリのフォークであり、D3.jsバージョン4との互換性で更新され、このクラシックライブラリに継続性を与えることを目的としています。 ECMAScript6とWebpackなどの新しい最新のツールを使用して記述されています。 そのAPIは、チャートに渡される構成オブジェクトに基づいているため、宣言型APIであると言えます。
ベガ
Vegaは宣言型パスをもう少し進め、JavaScriptオブジェクトから純粋なJSONファイルに構成を進化させます。 これは、データ視覚化の構成要素を形式化するLeland Wilkinsonの本であり、D3.jsのインスピレーションでもある、 The Grammar ofGraphicsに触発された視覚化文法を実装することを目的としています。 例の1つを開始点として選択して、エディターで遊ぶことができます。
D3FC
D3FCは、D3.jsとカスタムビルディングブロックを利用して、SVGとキャンバスの両方で強力なインタラクティブチャートを作成するのに役立ちます。 機能的で粒度の低いインターフェイスと大量のD3.jsコードを備えているため、強力ではありますが、おそらくある程度の学習が必要です。 その例を確認してください。
Britecharts
Britecharts —私がコアコントリビューターであるEventbriteによって作成されたライブラリ—は、MikeBostockが彼の投稿「TowardsReusableCharts」で普及し、NVD3などの他のライブラリで採用されているカプセル化パターンであるReusable ChartAPIを利用しています。 Britechartsは高レベルの抽象化を作成し、チャートの作成を容易にすると同時に、内部の複雑さを低く抑え、D3開発者がBritechartsを使用できるようにカスタマイズできるようにします。 洗練されたUIと多くの親しみやすいデモの構築に多くの時間を費やしました。
ライブラリをAPIで要約すると、次のように表すことができます。
React And The DOM
Reactは、コンポーネントを作成することでユーザーインターフェイスを構築するのに役立つJavaScriptライブラリです。 これらのコンポーネントは、状態を追跡し、プロパティを渡して効果的に再レンダリングし、アプリケーションのパフォーマンスを最適化します。
それはどのように機能しますか?
DOMの現在の状態を表す仮想DOMは、Reactの再レンダリングの最適化を可能にするテクノロジーです。 ライブラリは、複雑な差分アルゴリズムを使用して、条件が変化したときにアプリケーションのどの部分を再レンダリングする必要があるかを理解します。 この差分アルゴリズムは「調整アルゴリズム」と呼ばれます。
動的な子コンポーネント
アイテムのリストを含むコンポーネントをレンダリングする場合、開発者は子コンポーネントにアタッチされた一意の「キー」プロパティを使用する必要があります。 この値は、diffアルゴリズムが、新しいデータ(Reactワールドで呼び出される状態)がコンポーネントに渡されたときにアイテムを再レンダリングする必要があるかどうかを判断するのに役立ちます。 調整アルゴリズムは、キーの値をチェックして、アイテムを追加または削除する必要があるかどうかを確認します。 D3.jsのデータ結合について学習した後、これはなじみがありますか?
バージョン0.14以降、Reactはレンダラーを別のモジュールに保持します。 このように、同じコンポーネントを使用して、ネイティブアプリケーション(React Native)、仮想現実(React VR)、DOM(react-dom)などのさまざまなメディアでレンダリングできます。 この柔軟性は、SVGやキャンバスなどのさまざまなコンテキストでD3.jsコードをレンダリングする方法に似ています。
React And D3.js
ReactとD3はどちらも、高度に最適化された方法でDOMとその複雑さに対処するのを支援するという目標を共有しています。 また、純粋関数(特定の入力に対して、副作用を発生させることなく常に同じ出力を返すコード)とステートレスコンポーネントに対する優先順位も共有しています。
ただし、DOMに関する共通の懸念により、ユーザーインターフェイス要素をレンダリングおよびアニメーション化するかどうかを決定するときに、これら2つの意見のあるライブラリが衝突します。 この論争を解決するためのさまざまな方法を見ていきますが、簡単な答えはありません。 ただし、厳格なルールを確立することはできます。DOMコントロールを共有してはなりません。 それは災害のレシピになるでしょう。
アプローチ
ReactとD3.jsを統合する場合、D3.js側またはReact側にさらに傾いて、さまざまなレベルで統合できます。 4つの主な選択肢を見てみましょう。
React内のD3.js
私たちが従うことができる最初のアプローチは、D3コードに可能な限り多くのDOM制御を与えることです。 Reactコンポーネントを使用して、データ視覚化のルート要素として機能する空のSVG要素をレンダリングします。 次に、 componentDidUpdate
ライフサイクルメソッドを使用して、そのルート要素を使用し、バニラJavaScriptシナリオで使用するD3.jsコードを使用してグラフを作成します。 また、 shouldComponentUpdate
メソッドが常にfalse
を返すようにすることで、それ以降のコンポーネントの更新をブロックすることもできます。
class Line extends React.Component { static propTypes = {...} componentDidMount() { // D3 Code to create the chart // using this._rootNode as container } shouldComponentUpdate() { // Prevents component re-rendering return false; } _setRef(componentNode) { this._rootNode = componentNode; } render() { <div className="line-container" ref={this._setRef.bind(this)} /> } }
このアプローチを評価すると、いくつかの利点と欠点があることがわかります。 利点の中で、これはほとんどの場合正常に機能する単純なソリューションです。 また、既存のコードをReactに移植する場合、またはすでにどこかで機能していたD3.jsチャートを使用する場合にも、これは最も自然な解決策です。
欠点として、Reactコンポーネント内でReactコードとD3.jsコードの両方を混在させると、依存関係が多すぎてそのファイルが長すぎて高品質のコードと見なされないため、少し粗雑に見える可能性があります。 また、この実装はReact-idiomaticをまったく感じません。 最後に、ReactレンダリングサーバーはcomponentDidUpdate
メソッドを呼び出さないため、レンダリングされたバージョンのグラフを最初のHTMLで出荷することはできません。
React Faux DOM
オッリ・コールドウェルによって実装されたReact Faux DOMは、「既存のD3ツールを使用する方法ですが、Reactの精神でReactを介してレンダリングします」。 偽のDOM実装を使用して、D3.jsをだまして実際のDOMを処理していると思わせます。 このようにして、D3.jsをほぼすべての可能性で使用しながらReactDOMツリーを維持します。
import {withFauxDOM} from 'react-faux-dom' class Line extends React.Component { static propTypes = {...} componentDidMount() { const faux = this.props.connectFauxDOM('div', 'chart'); // D3 Code to create the chart // using faux as container d3.select(faux) .append('svg') {...} } render() { <div className="line-container"> {this.props.chart} </div> } } export default withFauxDOM(Line);
このアプローチの利点は、ほとんどのD3.js APIを使用できるため、すでに構築されているD3.jsコードと簡単に統合できることです。 また、サーバー側のレンダリングも可能です。 この戦略の欠点は、Reactの仮想DOMの前に別の偽のDOM実装を配置し、DOMを2回仮想化するため、パフォーマンスが低下することです。 この問題は、その使用を中小規模のデータ視覚化に限定します。
ライフサイクルメソッドのラッピング
Nicolas Heryによって最初に述べられたこのアプローチは、クラスベースのReactコンポーネントに存在するライフサイクルメソッドを利用します。 D3.jsチャートの作成、更新、削除をエレガントにラップし、ReactとD3.jsコードの間に明確な境界を確立します。
import D3Line from './D3Line' class Line extends React.Component { static propTypes = {...} componentDidMount() { // D3 Code to create the chart this._chart = D3Line.create( this._rootNode, this.props.data, this.props.config ); } componentDidUpdate() { // D3 Code to update the chart D3Line.update( this._rootNode, this.props.data, this.props.config, this._chart ); } componentWillUnmount() { D3Line.destroy(this._rootNode); } _setRef(componentNode) { this._rootNode = componentNode; } render() { <div className="line-container" ref={this._setRef.bind(this)} /> } }
D3Lineは次のようなものです。
const D3Line = {}; D3Line.create = (el, data, configuration) => { // D3 Code to create the chart }; D3Line.update = (el, data, configuration, chart) => { // D3 Code to update the chart }; D3Line.destroy = () => { // Cleaning code here }; export default D3Line;
この方法でコーディングすると、単純なAPI(作成、更新、削除)を介してD3.jsベースのチャートインスタンスと通信する軽量のReactコンポーネントが生成され、リッスンするコールバックメソッドが押し下げられます。
この戦略は、ファサードを使用してチャートの実装の詳細を非表示にすることで、関心の分離を促進します。 任意のグラフをカプセル化でき、生成されたインターフェイスは単純です。 もう1つの利点は、すでに作成されているD3.jsコードと簡単に統合でき、D3.jsの優れたトランジションを使用できることです。 この方法の主な欠点は、サーバー側のレンダリングができないことです。
DOMの場合はReact、数学の場合はD3
この戦略では、D3.jsの使用を最小限に抑えます。 これは、SVGパス、スケール、レイアウト、およびユーザーデータを取得してReactで描画できるものに変換する変換の計算を実行することを意味します。
DOMに関係のない多数のD3.jsサブモジュールのおかげで、数学のためだけにD3.jsを使用することが可能です。 このパスはReactに最も適したパスであり、FacebookライブラリにDOMの完全な支配を与えます。これは、非常にうまく機能します。
簡単な例を見てみましょう。
class Line extends React.Component { static propTypes = {...} drawLine() { let xScale = d3.scaleTime() .domain(d3.extent(this.props.data, ({date}) => date)); .rangeRound([0, this.props.width]); let yScale = d3.scaleLinear() .domain(d3.extent(this.props.data, ({value}) => value)) .rangeRound([this.props.height, 0]); let line = d3.line() .x((d) => xScale(d.date)) .y((d) => yScale(d.value)); return ( <path className="line" d={line(this.props.data)} /> ); } render() { <svg className="line-container" width={this.props.width} height={this.props.height} > {this.drawLine()} </svg> } }
この手法は、Reactの方法と一貫しているため、経験豊富なReact開発者のお気に入りです。 また、一度配置すると、そのコードを使用してグラフを作成するのは素晴らしい気分になります。 もう1つの利点は、サーバー側でのレンダリングであり、場合によってはReactNativeまたはReactVRです。
逆説的ですが、これはD3.jsがどのように機能するかについてより多くの知識を必要とするアプローチです。これは、そのサブモジュールと低レベルで統合する必要があるためです。 一部のD3.js機能を再実装する必要があります—軸と形状がより一般的です。 ブラシ、ズーム、ドラッグはおそらく最も難しいものです。これは、かなりの量の先行作業を意味します。
また、すべてのアニメーションを実装する必要があります。 Reactエコシステムには、アニメーションを管理できる優れたツールがあります(react-transition-group、react-motion、react-moveを参照)。ただし、SVGパスの複雑な補間を作成できるツールはありません。 保留中の1つの質問は、このアプローチを利用してHTML5のcanvas要素を使用してチャートをレンダリングする方法です。
次の図では、ReactとD3.jsの両方との統合レベルに応じて、説明されているすべてのアプローチを確認できます。
React-D3.jsライブラリ
私はD3.js-Reactライブラリについていくつかの調査を行いました。これは、作業、貢献、またはフォークするライブラリを選択するという決定に直面したときに役立つことを願っています。 いくつかの主観的な指標が含まれているので、一粒の塩と一緒に取ってください。
この調査により、多くの図書館がありますが、それらの多くは維持されていないことが明らかになりました。 私自身、メンテナとして、1つの主要な図書館の変更に対応するのがどれほど難しいか、そして2つの図書館の世話をしなければならないことは大変な作業になることを理解できます。
また、本番環境に対応したライブラリ(バージョン1.0.0以降)の数はまだかなり少ないです。 これはおそらく、このタイプのライブラリを出荷するために必要な作業量に関係しています。
私のお気に入りのいくつかを見てみましょう。
勝利
コンサルタント会社のFormidableLabsによるプロジェクトであるVictoryは、チャート要素の低レベルのコンポーネントライブラリです。 その低レベルの特性により、Victoryコンポーネントをさまざまな構成と組み合わせて、複雑なデータの視覚化を作成できます。 内部では、アニメーションにd3-interpolateを使用していますが、ブラシやズームなどのD3.js機能を再実装しています。
折れ線グラフに使用すると、次のようになります。
class LineChart extends React.Component { render() { return ( <VictoryChart height={400} width={400} containerComponent={<VictoryVoronoiContainer/>} > <VictoryGroup labels={(d) => `y: ${dy}`} labelComponent={ <VictoryTooltip style={{ fontSize: 10 }} /> } data={data} > <VictoryLine/> <VictoryScatter size={(d, a) => {return a ? 8 : 3;}} /> </VictoryGroup> </VictoryChart> ); } }
これにより、次のような折れ線グラフが生成されます。
Victoryの使用を開始するのは簡単で、ズームやツールチップ用のボロノイコンテナーなど、いくつかの優れたボーナスがあります。 これはトレンディなライブラリですが、まだプレリリース状態であり、多数のバグが保留されています。 現時点でReactNativeで使用できるライブラリはVictoryだけです。
再チャート
見た目に洗練され、楽しいユーザーエクスペリエンス、スムーズなアニメーション、見栄えの良いツールチップを備えたRechartsは、私のお気に入りのReact-D3.jsライブラリの1つです。 Rechartsは、d3-scale、d3-interpolate、およびd3-shapeのみを使用します。 Victoryよりも高いレベルの粒度を提供し、作成できるデータの視覚化の量を制限します。
Rechartsの使用は次のようになります。
class LineChart extends React.Component { render () { return ( <LineChart width={600} height={300} data={data} margin={{top: 5, right: 30, left: 20, bottom: 5}} > <XAxis dataKey="name"/> <YAxis/> <CartesianGrid strokeDasharray="3 3"/> <Tooltip/> <Legend /> <Line type="monotone" dataKey="pv" stroke="#8884d8" activeDot={{r: 8}}/> <Line type="monotone" dataKey="uv" stroke="#82ca9d" /> </LineChart> ); } }
このライブラリも非常によくテストされており、まだベータ版ですが、通常のチャート、レーダーチャート、ツリーマップ、さらにはブラシを備えています。 詳細については、その例を確認してください。 このプロジェクトに貢献している開発者は、真剣な取り組みを行い、アニメーションプロジェクトのreact-smoothでスムーズなアニメーションを実現しています。
Nivo
Nivoは、高レベルのReact-D3.jsチャートライブラリです。 レンダリングには多くのオプションがあります。SVG、キャンバス、さらにはサーバー側のレンダリングに最適なAPIベースのHTMLバージョンのグラフです。 アニメーションにはReactMotionを使用します。
APIは、チャートごとに1つの構成可能なコンポーネントのみを表示するため、少し異なります。 例を見てみましょう:
class LineChart extends React.Component { render () { return ( <ResponsiveLine data={data} margin={{ "top": 50, "right": 110, "bottom": 50, "left": 60 }} minY="auto" stacked={true} axisBottom={{ "orient": "bottom", "tickSize": 5, "tickPadding": 5, "tickRotation": 0, "legend": "country code", "legendOffset": 36, "legendPosition": "center" }} axisLeft={{ "orient": "left", "tickSize": 5, "tickPadding": 5, "tickRotation": 0, "legend": "count", "legendOffset": -40, "legendPosition": "center" }} dotSize={10} dotColor="inherit:darker(0.3)" dotBorderWidth={2} dotBorderColor="#ffffff" enableDotLabel={true} dotLabel="y" dotLabelYOffset={-12} animate={true} motionStiffness={90} motionDamping={15} legends={[ { "anchor": "bottom-right", "direction": "column", "translateX": 100, "itemWidth": 80, "itemHeight": 20, "symbolSize": 12, "symbolShape": "circle" } ]} /> ); } }
RaphaelBenitteはNivoで驚異的な仕事をしました。 ドキュメントは素敵で、そのデモは構成可能です。 このライブラリは抽象化レベルが高いため、使用が非常に簡単で、視覚化を作成する可能性が低いと言えます。 Nivoの優れた機能は、SVGパターンとグラデーションを使用してグラフを塗りつぶすことができることです。
VX
VXは、ビジュアライゼーションを作成するための低レベルのビジュアライゼーションコンポーネントのコレクションです。 これはピニオン化されておらず、他のチャートライブラリを作成するために、またはそのまま使用されることになっています。
いくつかのコードを見てみましょう:
class VXLineChart extends React.Component { render () { let {width, height, margin} = this.props; // bounds const xMax = width - margin.left - margin.right; const yMax = height - margin.top - margin.bottom; // scales const xScale = scaleTime({ range: [0, xMax], domain: extent(data, x), }); const yScale = scaleLinear({ range: [yMax, 0], domain: [0, max(data, y)], nice: true, }); return ( <svg width={width} height={height} > <rect x={0} y={0} width={width} height={height} fill="white" rx={14} /> <Group top={margin.top}> <LinePath data={data} xScale={xScale} yScale={yScale} x={x} y={y} stroke='#32deaa' strokeWidth={2} /> </Group> </svg> ); } };
この低レベルの粒度を考えると、VXはReactの世界のD3.jsだと思います。 ユーザーが使用したいアニメーションライブラリについては不可知論者です。 Airbnbの本番環境で使用されていますが、現在はまだ初期のベータ版です。 現時点での欠点は、ブラッシングやズームなどのインタラクションがサポートされていないことです。
Britecharts React
Britecharts Reactはまだベータ版であり、ライフサイクルメソッドラッピングアプローチを使用するこれらのライブラリの1つです。 使いやすいコードラッパーを作成することで、ReactでBritechartsの視覚化を使用できるようにすることを目的としています。
折れ線グラフの簡単なコードは次のとおりです。
class LineChart extends React.Component { render () { const margin = { top: 60, right: 30, bottom: 60, left: 70, }; return ( <TooltipComponent data={lineData.oneSet()} topicLabel="topics" title="Tooltip Title" render={(props) => ( <LineComponent margin={margin} lineCurve="basis" {...props} /> )} /> ); } }
私はこれについて客観的になることはできません。 Britecharts Reactは、D3.jsチャートをReactコンポーネントとしてレンダリングするための足場として使用できます。 サーバー側のレンダリングはサポートされていませんが、何らかの方法でこれを克服するためにロード状態が含まれています。
オンラインデモをチェックして、コードを試してみてください。
アプローチまたはライブラリの選択
チャートを使用してアプリケーションを構築する際の考慮事項を、品質、時間、範囲、およびコストの4つのカテゴリにグループ化しました。 それらは多すぎるので、単純化する必要があります。
品質を修正するとしましょう。 D3.jsバージョン4と包括的なドキュメントで最新の、十分にテストされたコードベースを持つことを目指すことができます。
時間について考えると、「これは長期的な投資ですか?」という質問が役立ちます。 応答が「はい」の場合は、D3.jsに基づいてライブラリを作成し、ライフサイクルメソッドアプローチを使用してReactでラップすることをお勧めします。 このアプローチは、テクノロジーによってコードを分離し、より時間に耐えます。
それどころか、プロジェクトの締め切りが厳しく、チームがそれを長期間維持する必要がない場合は、仕様に最も近いReact-D3.jsまたはD3.jsライブラリを取得し、フォークして使用することをお勧めします。 、途中で貢献しようとしています。
スコープを扱うときは、必要なのが少数の基本的なグラフなのか、1回限りの複雑な視覚化なのか、高度にカスタマイズされたグラフィックなのかを考える必要があります。 最初のケースでは、仕様に最も近いライブラリを再度選択してフォークします。 多くのアニメーションやインタラクションを含む特注のデータ視覚化には、通常のD3.jsで構築するのが最適なオプションです。 最後に、特定の仕様でさまざまなグラフを使用する場合(おそらく、UX担当者やデザイナーのサポートがある場合)、D3ライブラリを最初から作成するか、既存のライブラリをフォークしてカスタマイズするのが最適です。
最後に、決定のコスト面は、チームの予算とトレーニングに関連しています。 あなたのチームにはどのようなスキルがありますか? D3.js開発者がいる場合、彼らはD3.jsとReactを明確に分離することを好むので、おそらくライフサイクルメソッドラッピングを使用するアプローチがうまくいくでしょう。 ただし、チームのほとんどがReact開発者である場合、現在のReact-D3.jsライブラリのいずれかを拡張することを楽しんでいます。 また、D3.jsの例と一緒にライフサイクルメソッドを使用すると機能する可能性があります。 私がめったにお勧めしないのは、独自のReact-D3.jsライブラリをローリングすることです。 事前に必要な作業量は気が遠くなるほどであり、両方のライブラリの更新ペースにより、メンテナンスコストは簡単ではありません。
概要
ReactとD3.jsは、DOMとその課題に対処するのに役立つ優れたツールです。 彼らは確かに協力することができ、私たちはそれらの間に線を引く場所を選択する権限を与えられています。 D3.jsの使用を支援するために、ライブラリの健全なエコシステムが存在します。 React-D3.jsにも多くのエキサイティングなオプションがあり、両方のライブラリは絶えず進化しているため、両方を組み合わせたプロジェクトは追いつくのに苦労します。
選択は、1つの記事ですべてを説明することはできない非常に多くの変数に依存します。 ただし、主な考慮事項のほとんどをカバーし、情報に基づいた独自の決定を下せるようにしたいと考えています。
この基盤を使用して、興味を持って、言及されているライブラリを確認し、プロジェクトにチャートの良さを追加することをお勧めします。
これらのプロジェクトのいずれかを使用しましたか? もしそうなら、あなたの経験は何でしたか? コメントで私たちといくつかの言葉を共有してください。