Index
painterとは簡単な描画機能を提供してくれるパッケージ。
使い方は以下の記事にまとめてありますので、合わせて参照ください。
painter.dart内にある_PathHistoryクラスの_paths変数で保持されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
class _PathHistory { List<MapEntry<Path, Paint>> _paths; //ここにデータが保持される Paint currentPaint; Paint _backgroundPaint; bool _inDrag; bool get isEmpty => _paths.isEmpty || (_paths.length == 1 && _inDrag); _PathHistory() : _paths = <MapEntry<Path, Paint>>[], _inDrag = false, _backgroundPaint = new Paint()..blendMode = BlendMode.dstOver, currentPaint = new Paint() ..color = Colors.black ..strokeWidth = 1.0 ..style = PaintingStyle.fill; void setBackgroundColor(Color backgroundColor) { _backgroundPaint.color = backgroundColor; } void undo() { if (!_inDrag) { _paths.removeLast(); } } void clear() { if (!_inDrag) { _paths.clear(); } } void add(Offset startPoint) { if (!_inDrag) { _inDrag = true; Path path = new Path(); path.moveTo(startPoint.dx, startPoint.dy); _paths.add(new MapEntry<Path, Paint>(path, currentPaint)); } } void updateCurrent(Offset nextPoint) { if (_inDrag) { Path path = _paths.last.key; path.lineTo(nextPoint.dx, nextPoint.dy); } } void endCurrent() { _inDrag = false; } void draw(Canvas canvas, Size size) { canvas.saveLayer(Offset.zero & size, Paint()); for (MapEntry<Path, Paint> path in _paths) { Paint p = path.value; canvas.drawPath(path.key, p); } canvas.drawRect( new Rect.fromLTWH(0.0, 0.0, size.width, size.height), _backgroundPaint); canvas.restore(); } } |
重要なのは以下のコード
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Class Painter { //略 void _onPanStart(DragStartDetails start) { Offset pos = (context.findRenderObject() as RenderBox) .globalToLocal(start.globalPosition); widget.painterController._pathHistory.add(pos); widget.painterController._notifyListeners(); } void _onPanUpdate(DragUpdateDetails update) { Offset pos = (context.findRenderObject() as RenderBox) .globalToLocal(update.globalPosition); widget.painterController._pathHistory.updateCurrent(pos); widget.painterController._notifyListeners(); } void _onPanEnd(DragEndDetails end) { widget.painterController._pathHistory.endCurrent(); widget.painterController._notifyListeners(); } } |
onPanStart()メソッドで描画開始を検知します
1 2 3 4 5 6 |
void _onPanStart(DragStartDetails start) { Offset pos = (context.findRenderObject() as RenderBox) .globalToLocal(start.globalPosition);//① widget.painterController._pathHistory.add(pos);//② widget.painterController._notifyListeners();//③ } |
①描画された座標を変数posに格納(左上が(0,0))
以下の知識が必要になりますので、わからなければ参照してください。
②履歴にposを追加する
widget変数はPainterクラスにアクセスするための変数です。
addメソッドの中身は以下の通り。
currentPaint変数には描画の色や太さや線の種類が格納されている。
1 2 3 4 5 6 7 8 |
void add(Offset startPoint) { if (!_inDrag) { _inDrag = true; Path path = new Path(); path.moveTo(startPoint.dx, startPoint.dy); _paths.add(new MapEntry<Path, Paint>(path, currentPaint)); } } |
③履歴にposが追加されたことを通知する
changeNotifierクラスのnotifyListeners()を呼んでいる。
このメソッドが呼ばれると以下のメソッドが呼ばれて描画が実行される。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class _PainterPainter extends CustomPainter { //略 @override void paint(Canvas canvas, Size size) { _path.draw(canvas, size); } //略 void draw(Canvas canvas, Size size) { canvas.saveLayer(Offset.zero & size, Paint()); for (MapEntry<Path, Paint> path in _paths) { Paint p = path.value; canvas.drawPath(path.key, p); } canvas.drawRect( new Rect.fromLTWH(0.0, 0.0, size.width, size.height), _backgroundPaint); canvas.restore(); } } |
描画途中の処理と描画終わりの処理はほぼ同じなので説明は割愛します。