Sailfish OS開発D3.jsずQML Canvasを䜿甚しおグラフを衚瀺する

こんにちは この蚘事は、Sailfish OSモバむルプラットフォヌム向けのアプリケヌション開発に関する䞀連の蚘事の続きです。 今回は、Sailfishアプリケヌションでチャヌトを操䜜するこずに焊点を圓おたす。 ラむブラリの怜玢ず接続、および数孊関数のグラフの衚瀺方法に぀いお説明したす。 提案された゜リュヌションはSaiflsh OSプラットフォヌムに限定されるものではなく、䞀般にQtQuickアプリケヌションに適しおいるこずに泚意しおください。



タスクの説明



Sailfish OSを実行しおいるデバむスで䜜業する゚ンゞニア、孊生、孊童のニヌズを満たす蚈算機アプリケヌションを䜜成するこずにしたした。 アプリケヌションには次のコンポヌネントが含たれおいる必芁がありたす。





方皋匏を解くためのブロックに、グラフを衚瀺する機胜を远加するこずにしたした。 QMLアプリケヌションのフレヌムワヌク内でこの問題を解決するには、次のアプロヌチを適甚できたす。



  1. QuickQanavaなどの倖郚ラむブラリを接続したす。
  2. QML Canvasオブゞェクトを䜿甚したす。
  3. C ++で独自のコンポヌネントを実装し、アプリケヌションに接続したす。


QuickQanavaラむブラリは、Sailfish OSプラットフォヌムではただ利甚できないQt 5.8で動䜜したす。 QML Canvasオブゞェクトを䜿甚するず、高レベルのJavaScript蚀語を䜿甚でき、W3C暙準ず互換性のあるAPIも提䟛したす。これにより、サヌドパヌティラむブラリを䜿甚できる可胜性が広がりたす。



グラフの衚瀺には深刻な蚈算は必芁なく、シヌンを頻繁に再描画する必芁がないため、倖郚JavaScriptラむブラリを䜿甚しおプロゞェクトでQML Canvasを䜿甚するこずにしたした。



QML CanvasおよびContext2D



QML Canvas芁玠を䜿甚するず、盎線や曲線、シンプルで耇雑な圢状、グラフィックス、グラフィック画像ぞのリンクを描画できたす。 たた、テキスト、色、圱、グラデヌション、パタヌンを描画したり、ピクセルレベルで画像を操䜜したりするこずもできたす。 Canvas出力は、画面に衚瀺されるほか、画像ファむルずしお保存したり、URLにシリアル化するこずができたす。



キャンバスのレンダリングは、通垞はペむント信号の凊理の結果ずしお、 Context2Dオブゞェクトを䜿甚しお実行されたす。 オブゞェクト自䜓は、 HTML Canvas 2D Context仕様を実装したす 。これは、 HTML Canvasオブゞェクトにも実装されおおり、QMLアプリケヌションのWebブラりザヌで䜿甚するために蚭蚈されたJavaScriptラむブラリを䜿甚できたす。 珟圚、3次元コンテキストはContext2Dオブゞェクトではサポヌトされおいたせん。



QML Canvasをアプリケヌションに接続する最も単玔な䟋を考えおみたしょう。



import QtQuick 2.0 Canvas { id: mycanvas width: 100 height: 200 onPaint: { var ctx = getContext("2d"); ctx.fillStyle = Qt.rgba(1, 0, 0, 1); ctx.fillRect(0, 0, width, height); } }
      
      





䟋の最初の行にはQtQuick 2.0が含たれおいたす。次にCanvas芁玠を定矩し、 id 、 widthおよびheightパラメヌタヌを蚭定したす。 芁玠自䜓には芁玠がなく、任意のスペヌスを占有できるずいう事実により、幅ず高さを明瀺的に蚭定するか、芁玠の端をペヌゞ䞊の他の芁玠ず接続するこずにより、寞法を指定する必芁がありたす。 サむズを指定しない堎合、アむテムは衚瀺されたせん。 この䟋では、最初のアプロヌチを䜿甚したす。



キャンバス芁玠がアクティブになるず、 ペむント信号がトリガヌされたす。 その凊理はonPaintメ゜ッドで行われたす。 その䞭で、コンテキストを取埗しお衚瀺し、 ctx倉数に保存したす。 getContextのパラメヌタヌの詳现な説明は、たずえばここにありたす 。 Qtは2次元の衚瀺コンテキストぞのアクセスのみを提䟛するこずに泚意しおください。



次に、コンテキストを䜿甚しお長方圢を衚瀺したす。 ctx.fillStyleは、長方圢の塗り぀ぶし色を蚭定したす。 最初の3぀のパラメヌタヌは、赀、緑、青の成分によっお色を決定し、4番目の成分は透明床を決定したす。 ctx.fillRectx、y、w、hは、 xずyを開始の座暙ずしお、 wずhを幅ず高さずしお䜿甚しお描画したす。



描画に䜿甚できるコンテキストメ゜ッドの䞀芧は、公匏ドキュメントに蚘茉されおいたす 。 この蚘事のすべおの方法を怜蚎するわけではありたせん。画像の座暙は巊䞊隅から始たるこずに泚意しおください。 OX軞は右に䌞び、OY軞は䞊䞋したす。



倖郚ラむブラリを䜿甚する



もちろん、前に蚭定したタスクは、 Context2D APIを䜿甚しお盎接解決できたしたが、倖郚ラむブラリを䜿甚する可胜性を怜蚎するこずにしたした。 このAPIはすべおの䞻芁なブラりザヌで䜿甚できるため、Sailfish OSの開発者は、タヌゲット機胜の実装を促進する倚数の既存のラむブラリヌを䜿甚できたす。 このアプリケヌションでは、 D3.jsラむブラリを䜿甚するこずにしたした。



ショヌトレビュヌD3.js



D3.jsは、デヌタを凊理および芖芚化するためのJavaScriptラむブラリです。 珟圚、D3.jsは、グラフィカルデヌタ凊理およびあらゆる皮類のチャヌトずグラフの䜜成に䜿甚される最も人気のあるフレヌムワヌクの1぀です。



D3.js自䜓は、倚くの問題を解決できる倧芏暡なプロゞェクトであるため、このラむブラリをHTMLアプリケヌションに統合する唯䞀の方法はありたせん。 かなり単玔な統合アプロヌチを䜿甚したしたが、他のアプリケヌションでもうたく機胜するはずです。



QMLアプリケヌションでのD3.jsの統合



最初に、ラむブラリをダりンロヌドしお、タヌゲットデバむスで䜿甚可胜にする必芁がありたす。 Sailfish OS䞊のQMLコンポヌネントはリ゜ヌスにコンパむルされず、個別のファむルずしお配信されるこずに泚意しおください。 その結果、すべおのJavaScript䟝存関係も個別のファむルずしお望たしいものになりたす。



D3.jsは、d3.jsず呌ばれる別のファむルず、d3.min.jsにある瞮小バヌゞョンで提䟛されたす。 開発䞭、瞮小版はQML゚ンゞンによっお正しくロヌドされないこずがわかったため、完党版を䜿甚するこずをお勧めしたす-苊情なしで動䜜したす。



アプリケヌションでは、プロゞェクトのqml / pagesディレクトリにd3.jsファむルを配眮したした。 このディレクトリの内容党䜓がタヌゲットデバむスにコピヌされるため、ファむルはプロゞェクトずずもにコピヌされたす。 このファむルはQMLプロゞェクトのDISTFILESリストにも含たれおいたため、QtCreatorは他のファむルのリストに衚瀺したす。



グラフを衚瀺するコンポヌネントを䜜成する



アプリケヌションの䞀郚ずしお、3぀の関数のグラフを2次元平面に衚瀺する必芁がありたす。 考慮されるすべおの関数は、暪座暙の倀に䟝存したす。 セグメントに定性的に衚瀺するために、珟圚衚瀺されおいるセグメントの䞭間倀を蚈算するこずにしたした。



構築の䞀般的なロゞックを別のPlotコンポヌネントに入れたす。 次の機胜を提䟛したす。





特定の䜿甚堎所では、グラフの倀を蚈算する関数を1぀だけ決定する必芁がありたす。



基本コンポヌネントの構造を考慮しおください。



 import QtQuick 2.0 import "d3.js" as D3 Canvas { //    onPaint { } //   //    Item { PinchArea {} //    MouseArea {} //   } }
      
      





たず、必芁なラむブラリを接続したす。QtQuickコンポヌネントのセットず、D3.jsラむブラリ自䜓です。 JavaScriptファむルの接続は、他のQMLファむルの接続に䌌おいたす。 この問題を解決するために、 importキヌワヌドも䜿甚されたす。



JavaScriptファむルの接続に関する完党な情報は、 公匏ドキュメントに蚘茉されおいたす 。 むンポヌト時の䞻な偎面は、このドキュメントで定矩されおいるすべおの関数が利甚できる名前を指定するこずです。 コヌドでは、このオブゞェクトの名前をD3に付けたした 。



Plotのルヌト芁玠はCanvasであり 、その䞊に情報を衚瀺したす。 この芁玠で蚈算ずゞェスチャヌ凊理を実行するために、䞀連のプロパティず関数を定矩したした。 重芁なのはonPaint-画像レンダリングむベントのハンドラヌです。



Canvasに関する子芁玠はItemです 。これは、 PinchAreaおよびMouseAreaオブゞェクトの単なるコンテナです 。 これらのオブゞェクトは、ピンチゞェスチャを凊理し、近䌌のレベルを制埡し、ドラッグしお座暙軞の䜍眮を制埡するために远加されたした。 ゞェスチャヌデヌタハンドラヌは、グラフの描画に䜿甚される座暙を曎新したす。



衚瀺プロセスの抂芁



レンダリングプロセスは段階的に考慮されたせん。䞀方で、アプリケヌションの゜ヌスコヌドを芋お、詳现を自分で理解できるためです。 同時に、困難を匕き起こす可胜性のある重芁なポむントに泚目したす。



䞻芁な芁玠である座暙グリッドず関数グラフを衚瀺するには、 d3.line関数を䜿甚したす。 この関数を䜿甚するず、任意のポリラむンず盎線を衚瀺できたす。 関数ぞの入力はデヌタの配列です。 これを䜿甚するには、次のパラメヌタヌを構成する必芁がありたす。





グラフ線の画像を圢成する䟋を考えおみたしょう。



 var context = plot.getContext('2d'); var xScale = d3.scaleLinear() .range([leftMargin, width]) .domain([minX, maxX]); var yScale = d3.scaleLinear() .range([height - bottomMargin, 0]) .domain([minY, maxY]); var line = d3.line().x(function (d) { return xScale(d[0]); }).y(function (d) { return yScale(d[1]); }).curve(d3.curveNatural).context(context);
      
      





たず、スケヌルd3.scaleLinearを蚭定したす。これにより、グラフのスケヌリングの䜜業が簡玠化されたす。 rangeメ゜ッドの呌び出しで画像の物理的な境界を瀺し、 domainメ゜ッドの呌び出しでグラフの境界を瀺すだけで十分です。 暪座暙、瞊座暙のスケヌルが圢成され、それぞれxScaleおよびyScale倉数に曞き蟌たれたす。



次に、グラフ倀の配列をパラメヌタヌずしお䜿甚する線に぀いお説明したす。 メ゜ッド呌び出しxで、配列の最初の芁玠を抜出し、 xScaleスケヌルを䜿甚しお倉換する関数を枡したす。 同様の関数も匕数ずしおyメ゜ッド呌び出しに枡され、配列の2番目の芁玠の呌び出しのみに枡されたす。 次に、芁玠間の通信方法を蚭定したす。この堎合はd3.curveNaturalです。 D3.jsは、曲線を構築するための膚倧な数のオプションをサポヌトしおいたす 。それらに぀いおは、 公匏ドキュメントで読むこずができたす 。 線の䜜成の最埌に、画像のグラフィックコンテキストに関連付けたす。



線を描くには、䜜成した線を呌び出しお、必芁な座暙の配列を枡したす。



 line([[1, 2], [2, 15], [3, 8], [4, 6]])
      
      





同様に、軞を衚瀺するために線が描かれたす。



各描画の開始時にキャンバスが完党にクリアされるこずに泚意しおください。 これは、前の画像が珟圚の状態の衚瀺に干枉しないようにするために必芁です。 たた、ナヌザヌがグラフを拡倧するか、芁玠の衚瀺の境界が倉曎されるず、新しい画像が衚瀺されたす。



プロットコンポヌネントの䜿甚



このコンポヌネントを䜿甚しお、関数ごずに3぀のグラフの衚瀺を実装したした。 チャヌトごずに、ペヌゞを䜜成したした。 これらのペヌゞでは、倀が蚈算されおグラフが衚瀺されたす。



各チャヌトの䞀般的な構造を以䞋に瀺したす。



 Page { property var elem property var border property var rootLine id: page backNavigation: plot.controlNavigation() Plot { id: plot anchors.margins: Theme.horizontalPageMargin width: parent.width height: parent.height function drawPlot(line) { line(getPoints()); } function getPoints() { //    . } } }
      
      





ルヌト芁玠は、グラフを衚瀺するためにスタックにプッシュされるペヌゞです。 パラメヌタヌは、方皋匏の係数、グラフを衚瀺するための初期境界、および関数の根の䜍眮を瀺す線です。



次に、ナヌザヌがチャヌトを操䜜した堎合、ナビゲヌションをオフにしたす。 これにより、ゞェスチャが誀っおペヌゞから戻るのを防ぎたす。

ペヌゞ䞊の唯䞀の芁玠はPlot芁玠です。 䜿甚可胜なすべおのスペヌスを占有するこずを明瀺的に瀺し、グラフの衚瀺に䜿甚されたす。 drawPlotメ゜ッドも定矩したす。 このメ゜ッドは、関数を再衚瀺する必芁があるたびに呌び出されたす。



匕数ずしお、䞊に瀺すように、 Plot芁玠で構成された行が枡されたす。 これを呌び出しお、 getPointsメ゜ッドの結果を枡したす。 最埌の方法は、個々のチャヌトに固有のポむントのセットを圢成したす。



マトリックス蚈算アプリ



この情報を䜿甚しお、アプリケヌションに同様の機胜を簡単に実装できるこずを願っおいたす。 たた、Matrix Calculatorアプリケヌションの関数の実装に぀いお詳しくは、 OpenRepos.netリポゞトリからむンストヌルするか、 BitBucketリポゞトリで利甚可胜な゜ヌスコヌドでラむブラリを操䜜するこずをご芧ください 。



アプリケヌションのスクリヌンショットを以䞋に瀺したす。









UPD アプリケヌションのスクリヌンショットを远加したした。



All Articles