canvas要素でのReactの使用について

このような素晴らしいReactフレームワークがあり、これにより、美しく不変の機能的なスタイルで巨大で可変のDOMを扱うことができます。 これは本当にクールです。



しかし、Reactを使用した経験についてお話したいと思います。Reactを使用すると、「不変の」キャンバス要素で可変の抽象化を操作できます。 奇妙に聞こえますが、うまく機能します。



やる気



<canvas>



頻繁に使用し<canvas>



。 キャンバスがデータプレゼンテーションの主要な要素である、かなり複雑なWebアプリケーションをいくつか作成しました。 フレームワークやライブラリなしでキャンバスを使用することは、大規模なアプリケーションでは非常に困難です。 だから、フレームワークを頻繁に使い始めました。 今、私はKonvaフレームワークをサポートしています(レビュー記事https://habrahabr.ru/post/250897/があります )。



Konvaは大いに役立ちますが、もっと欲しいです。 また、アプリケーションでReactを使い始めましたが、本当に気に入っています。 そして、Reactを使用してキャンバスにグラフィックを描画するにはどうすればよいと思いましたか?



React +キャンバス





React +フレームワークなしのキャンバス



Reactコンポーネントからキャンバスコンテキストにアクセスし、何かを描画するのは非常に簡単です。



 class CanvasComponent extends React.Component { componentDidMount() { this.updateCanvas(); } updateCanvas() { const ctx = this.refs.canvas.getContext('2d'); ctx.fillRect(0,0, 100, 100); } render() { return ( <canvas ref="canvas" width={300} height={300}/> ); } } ReactDOM.render(<CanvasComponent/>, document.getElementById('container'));
      
      





デモ: http : //jsbin.com/xituko/edit?js,output



簡単な例に最適です。 ただし、大規模なアプリケーションの場合、この方法はあまり効果的ではありません。組み込みのReactコンポーネントを作成できないためです。



 // ,     function rect(props) { const {ctx, x, y, width, height} = props; ctx.fillRect(x, y, width, height); } class CanvasComponent extends React.Component { componentDidMount() { this.updateCanvas(); } componentDidUpdate() { this.updateCanvas(); } updateCanvas() { const ctx = this.refs.canvas.getContext('2d'); ctx.clearRect(0,0, 300, 300); //  ""  rect({ctx, x: 10, y: 10, width: 50, height: 50}); rect({ctx, x: 110, y: 110, width: 50, height: 50}); } render() { return ( <canvas ref="canvas" width={300} height={300}/> ); } } ReactDOM.render(<CanvasComponent/>, document.getElementById('container'));
      
      





そして、かなり便利な反応メソッド(「shouldComponentUpdate」、「componentDidMountなど」など)はどうでしょうか。

しかし、「レンダリング関数のビューの完全な説明」アプローチについてはどうでしょうか?



実装



アプリケーションを構築するための反応的なアプローチが本当に好きです。 そこで、Konvaフレームワークを介してキャンバスに描画するreact-konvaプラグインを作成しました。



 npm install react konva react-konva --save
      
      





次へ



 import React from 'react'; import ReactDOM from 'react-dom'; import {Layer, Rect, Stage, Group} from 'react-konva'; class MyRect extends React.Component { constructor(...args) { super(...args); this.state = { color: 'green' }; this.handleClick = this.handleClick.bind(this); } handleClick() { this.setState({ color: Konva.Util.getRandomColor() }); } render() { return ( <Rect x={10} y={10} width={50} height={50} fill={this.state.color} shadowBlur={10} onClick={this.handleClick} /> ); } } function App() { return ( <Stage width={700} height={700}> <Layer> <MyRect/> </Layer> </Stage> ); } ReactDOM.render(<App/>, document.getElementById('container'));
      
      





デモ: http : //jsbin.com/camene/5/edit?html,js,output



比較



反応するコンバ対反応するキャンバス



react-canvasは完全に異なるプラグインです。 これにより、非常に高いパフォーマンスで「標準DOMオブジェクト」(画像、テキスト)を描画できます。 ただし、このプラグインではグラフィックスを描画できません。 一方、 react-konvaは、Reactを使用してキャンバスに複雑なグラフィックを描画するために特別に作成されています。



反応するコンバ対反応するアート



react-artでは、グラフィックを描画することもでき、SVGをサポートしていますが、グラフィックフィギュアのイベントサポートはありません。



反応コンバ対バニラキャンバス



彼らはReactについて言及するとき、生産性について非常に頻繁に話します。 実際、Reactを使用する主な理由の1つは、パフォーマンスの問題を解決することです。



しかし、パフォーマンスの問題を解決するためではなく、このプラグインを使用しました。 キャンバスを直接使用することが最も生産的な方法であるはずなので、 react-konvaを使用すると 、キャンバスの上で実行されるKonvaと、Konvaの上で実行されるReactがあります。



しかし、アプリケーションの複雑さに対処するプラグインを作成しました。 Konvaは非常に役立ちます(特に、「クリック」など、キャンバス上のオブジェクトにイベントが必要な場合、フレームワークなしでこれを行うのは非常に困難です)。 しかし、Reactは非常に優れたコード構造とデータ移動を提供するため、さらに役立ちます。



特徴



konvaロゴ



react-konvaは、円、四角形、楕円、線、スプライト、画像、テキスト、TextPath、星、リング、円弧、ラベル、SVGパス、RegularPolygon、矢印などの基本的な図形を多数サポートしており、独自の図形を作成できます。 ドラッグアンドドロップ、アニメーション、フィルター、キャッシュシステム、デスクトップおよびモバイルイベント(マウス入力、クリック、dblclick、dragstart、dragmove、dragend、tap、dbltapなど)の組み込みサポートもあります。



カスタム形状の例



 function MyShape() { return ( <Shape fill=”#00D2FF” draggable sceneFunc={function (ctx) { ctx.beginPath(); ctx.moveTo(20, 50); ctx.lineTo(220, 80); ctx.quadraticCurveTo(150, 100, 260, 170); ctx.closePath(); // Konva specific method ctx.fillStrokeShape(this); }} /> ); }
      
      





デモ: http : //jsbin.com/gakadi/2/edit?html,js,output



イベントの例



 class MyCircle extends React.Component { constructor(…args) { super(…args); this.state = { isMouseInside: false}; this.handleMouseEnter = this.handleMouseEnter.bind(this); this.handleMouseLeave = this.handleMouseLeave.bind(this); } handleMouseEnter() { this.setState({ isMouseInside: true}); } handleMouseLeave() { this.setState({ isMouseInside: false}); } render() { return ( <Circle x={100} y={60} radius={50} fill=”yellow” stroke=”black” strokeWidth={this.state.isMouseInside ? 5 : 1} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} /> ); } }
      
      





デモ: http : //jsbin.com/tekopu/1/edit



参照資料



Github: https : //github.com/lavrton/react-konva

Konvaフレームワーク: http ://konvajs.github.io/




All Articles