使用CustomPainter在Flutter中繪圖

介紹 :

在Flutter中,所有內(nèi)容都圍繞Widget。Flutter讓你靈活創(chuàng)建一些漂亮的UI小部件,并且該應(yīng)用程序可以在iOS和Android上使用。因此,將您創(chuàng)建的這些小部件繪制到移動(dòng)屏幕上,或者我們可以將其稱為繪制在畫布上(Canvas)。那么我們也可以將其用作繪圖板來(lái)繪圖。

我們將使用custom painter在畫布上繪畫,我們將提供更改畫筆的大小,不透明度和顏色的選項(xiàng)。

該代碼位于https://github.com/sharansingh00002/draw

現(xiàn)在讓我們來(lái)看看這是如何完成的:)

Code Time

我們需要具備的第一個(gè)信息是用戶與之交互的畫布上的點(diǎn)的坐標(biāo),我們可以使用Gesture Detector輕松獲得該信息。我們將使用手勢(shì)檢測(cè)器的onPanUpdate,onPanStartonPanEnd屬性。當(dāng)用戶單擊屏幕時(shí)使用onPanStart,這樣我們可以繪制一個(gè)點(diǎn),但是如果用戶拖動(dòng),則使用onPanUpdate可以獲取連續(xù)點(diǎn),并且OnPanEnd通知用戶已停止繪制。

我們將這些點(diǎn)存儲(chǔ)在列表中,其中每個(gè)元素將具有坐標(biāo)以及與該點(diǎn)關(guān)聯(lián)的繪制屬性。

class DrawingPoints {
  Paint paint;
  Offset points;
  DrawingPoints({this.points, this.paint});
}

在手勢(shì)檢測(cè)器中,onPanUpdate函數(shù)看起來(lái)像

onPanUpdate: (details) {
  setState(() {
    RenderBox renderBox = context.findRenderObject();
    points.add(DrawingPoints(
        points: renderBox.globalToLocal(details.globalPosition),
        paint: Paint()
          ..strokeCap = strokeCap
          ..isAntiAlias = true
          ..color = selectedColor.withOpacity(opacity)
          ..strokeWidth = strokeWidth));
  });
},
onPanStart: (details) {
  setState(() {
    RenderBox renderBox = context.findRenderObject();
    points.add(DrawingPoints(
        points: renderBox.globalToLocal(details.globalPosition),
        paint: Paint()
          ..strokeCap = strokeCap
          ..isAntiAlias = true
          ..color = selectedColor.withOpacity(opacity)
          ..strokeWidth = strokeWidth));
  });
},
onPanEnd: (details) {
  setState(() {
    points.add(null);
  });
},

因此,我們使用渲染框獲取要在其上進(jìn)行繪制的渲染對(duì)象,并將該框的全局坐標(biāo)系點(diǎn)轉(zhuǎn)換為局部坐標(biāo)系。我們將在末尾添加null以標(biāo)記繪圖的結(jié)束。

現(xiàn)在讓我們看一下自定義的CustomPainter類,該類負(fù)責(zé)在屏幕上繪制。

class DrawingPainter extends CustomPainter {
  DrawingPainter({this.pointsList});
  List<DrawingPoints> pointsList;
  List<Offset> offsetPoints = List();
  @override
  void paint(Canvas canvas, Size size) {
    for (int i = 0; i < pointsList.length - 1; i++) {
      if (pointsList[i] != null && pointsList[i + 1] != null) {
        canvas.drawLine(pointsList[i].points, pointsList[i +1].points ,
            pointsList[i].paint);
      } else if (pointsList[i] != null && pointsList[i + 1] == null) {
        offsetPoints.clear();
        offsetPoints.add(pointsList[i].points);
        offsetPoints.add(Offset(
            pointsList[i].points.dx + 0.1, pointsList[i].points.dy + 0.1));
        canvas.drawPoints(PointMode.points, offsetPoints, pointsList[i].paint);
      }
    }
  }
  @override
  bool shouldRepaint(DrawingPainter oldDelegate) => oldDelegate.pointsList!=pointsList;
}

我們使用Canvas.drawLine函數(shù)繪制線條,但是如果用戶剛剛在屏幕上輕擊,則使用Canvas.drawPoint繪制該點(diǎn)。

我們正在檢查是否為null,因?yàn)樵谟脩敉V估L圖時(shí)我們將添加null,以便如果他再次開始繪圖,則最后一個(gè)繪圖的最后一點(diǎn)和新繪圖的起點(diǎn)不應(yīng)該連接。

要清除屏幕,只需清除pointsList。

定制:

因此,我們可以添加許多自定義項(xiàng),到目前為止,我已經(jīng)添加了更改筆觸寬度,筆刷的不透明度和顏色的選項(xiàng)。

因此,對(duì)于strokeWidth不透明度Opacity,我們可以簡(jiǎn)單地使用Slider來(lái)更改值,對(duì)于Color,我們提供一些預(yù)定義的最常用的顏色,以及使用顏色選擇器選擇其選擇的顏色的選項(xiàng)。

這些更改的值存儲(chǔ)在與每個(gè)繪圖點(diǎn)關(guān)聯(lián)的Paint對(duì)象中,以便每個(gè)點(diǎn)可以具有自己的特征。

Slider(
    value: (selectedMode == SelectedMode.StrokeWidth)
        ? strokeWidth
        : opacity,
    max: (selectedMode == SelectedMode.StrokeWidth)
        ? 50.0
        : 1.0,
    min: 0.0,
    onChanged: (val) {
      setState(() {
        if (selectedMode == SelectedMode.StrokeWidth)
          strokeWidth = val;
        else
          opacity = val;
      });
    }),

對(duì)于顏色選擇器,我們使用fuyumi的flutter_colorpicker庫(kù)https://pub.dartlang.org/packages/flutter_colorpicker

這個(gè)項(xiàng)目的代碼可以在github上找到:

https://github.com/sharansingh00002/draw

翻譯自:https://medium.com/flutter-community/drawing-in-flutter-using-custompainter-307a9f1c21f8

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容