Flutter之簡單繪圖

Flutter中如果想要自定義繪制丢郊,那么你需要用到 CustomPaint 和 CustomPainter ; CustomPaint是Widget的子類。

const CustomPaint({
    Key key,
    this.painter,
    this.foregroundPainter,
    this.size = Size.zero,
    this.isComplex = false,
    this.willChange = false,
    Widget child,
  }) :super(key: key, child: child);

示例

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Painter繪制直線'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: CustomPaint(
          size: Size(300, 300),
          painter:MyPainter() ,
        ),
      )
    );
  }
}

class MyPainter extends CustomPainter {
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.fill //繪畫風格棚放,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
     canvas.drawLine(Offset(20, 20), Offset(100,100), _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return null;
  }
}

定義畫筆

///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.fill //繪畫風格家乘,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

繪制直線(drawLine)

使用給定的涂料在給定點之間繪制一條線娜汁。 該行被描邊党晋,此調(diào)用忽略[Paint.style]的值寻咒。p1和p2參數(shù)為兩個點的坐標 , 在這兩點之間繪制一條直線哮翘。

class MyPainter extends CustomPainter {
///[定義畫筆]
Paint _paint = Paint()
..color = Colors.blueAccent //畫筆顏色
..strokeCap = StrokeCap.round//畫筆筆觸類型
..isAntiAlias = true //是否啟動抗鋸齒
..style = PaintingStyle.fill //繪畫風格,默認為填充
..strokeWidth = 5.0; //畫筆的寬度

@override
void paint(Canvas canvas, Size size) {
 canvas.drawLine(Offset(20, 20), Offset(100,100), _paint);
}

@override
bool shouldRepaint(CustomPainter oldDelegate) {
return null;
}
}
image.png

繪制點(drawPoints)

繪制點也是非常的簡單毛秘,3個參數(shù)分別為: PointMode枚舉饭寺,坐標 list 和 paint。PointMode的枚舉類型有三個叫挟,points(點)艰匙,lines(線,隔點連接)抹恳,polygon(線员凝,相鄰連接)

void drawPoints(PointMode pointMode, List points, Paint paint)
class MyPainter extends CustomPainter {
  
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.fill //繪畫風格,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
    ///PointMode的枚舉類型有三個奋献,points(點)健霹,lines(線,隔點連接)瓶蚂,polygon(線糖埋,相鄰連接)
     canvas.drawPoints(
       PointMode.points,
       [
         Offset(20.0,  40.0),
         Offset(100.0, 120.0),
         Offset(100.0, 220.0),
         Offset(200.0, 220.0),
         Offset(200.0, 120.0),
         Offset(280.0, 40.0),
         Offset(20,    40.0),
       ], 
       _paint
       );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return null;
  }
}

PointMode改為points

image.png

PointMode改為polygon, PointMode改為polygon,相鄰點互相連接
image.png

PointMode改為lines窃这。 PointMode為lines時瞳别,兩個點相互連接,也就是說第一個和第二個點連接钦听,第三個跟第四個連接洒试,如果最后只有一個點就舍棄不連接了,在我們的例子中有7個點朴上,所以圖中只有三條連線垒棋。

image.png

繪制圓drawCircle

參數(shù)分別為:圓心的坐標、半徑和paint即可痪宰。圓形是否填充或描邊(或兩者)由Paint.style控制叼架。

void drawCircle(Offset c, double radius, Paint paint)
class MyPainter extends CustomPainter {
  
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.stroke //繪畫風格,默認為不填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
    //繪制圓 參數(shù)(圓心衣撬,半徑乖订,畫筆)
    canvas.drawCircle(Offset(140,80), 80,_paint..color = Colors.green);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return null;
  }
}
image.png

PaintStyle.fill 填充

image.png

繪制橢圓drawOval

制一個軸對稱的橢圓形,參數(shù)為一個矩形和畫筆paint.

void drawOval(Rect rect, Paint paint)
class MyPainter extends CustomPainter {
  
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.fill //繪畫風格具练,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
    //使用左上和右下角坐標來確定矩形的大小和位置,橢圓是在這個矩形之中內(nèi)切的
    Rect rect = Rect.fromPoints(Offset(100.0, 40.0), Offset(220.0, 100.0));
    canvas.drawOval(rect, _paint..color=Colors.green);
  }
}

Rect也有多種構(gòu)建方式: fromLTWH(double left, double top, double width, double height) 使用矩形左邊的X坐標乍构、矩形頂部的Y坐標矩形的寬高來確定矩形的大小和位置

@override
  void paint(Canvas canvas, Size size) {
    //使用矩形左邊的X坐標、矩形頂部的Y坐標矩形的寬高來確定矩形的大小和位置
    Rect rect = Rect.fromLTWH(100, 20, 100, 60);
    canvas.drawOval(rect, _paint..color=Colors.green);
  }

image.png

fromLTRB(double left, double top, double right, double bottom) 使用矩形左邊的X坐標扛点、矩形頂部的Y坐標哥遮、矩形右邊的X坐標岂丘、矩形底部的Y坐標來確定矩形的大小和位置

@override
  void paint(Canvas canvas, Size size) {
    //使用矩形左邊的X坐標、矩形頂部的Y坐標眠饮、矩形右邊的X坐標奥帘、矩形底部的Y坐標來確定矩形的大小和位置
    Rect rect = Rect.fromLTRB(30, 30, 160, 140);
    canvas.drawOval(rect, _paint..color=Colors.green);
  }
image.png

fromCircle({ Offset center, double radius }) 使用圓的圓心點坐標和半徑和確定外切矩形的大小和位置

@override
  void paint(Canvas canvas, Size size) {
    //使用圓的圓心點坐標和半徑和確定外切矩形的大小和位置
    Rect rect = Rect.fromCircle(center: Offset(100, 40),radius: 60);
    canvas.drawOval(rect, _paint..color=Colors.green);
  }
image.png

繪制圓弧drawArc

首先還是需要Rect來確認圓弧的位置,還需要開始的弧度仪召、結(jié)束的弧度寨蹋、是否使用中心點繪制(圓弧是否向中心閉合)、以及paint.

void drawArc(Rect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint)
class MyPainter extends CustomPainter {
  
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.fill //繪畫風格扔茅,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
    // Rect來確認圓弧的位置已旧,還需要開始的弧度、結(jié)束的弧度咖摹、是否使用中心點繪制评姨、以及paint弧度
    Rect rect = Rect.fromCircle(center: Offset(100, 40),radius:80);
    canvas.drawArc(rect,0.0,0.8,false,_paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return null;
  }
}

圓弧向中心點閉合 將useCenter改成true,圓弧向中心點閉合了

@override
  void paint(Canvas canvas, Size size) {
    // Rect來確認圓弧的位置萤晴,還需要開始的弧度、結(jié)束的弧度胁后、是否使用中心點繪制店读、以及paint弧度
    const PI = 3.1415926;
    Rect rect2 = Rect.fromCircle(center: Offset(100.0, 50.0), radius: 80.0);
    canvas.drawArc(rect2, 0.0, PI / 2, true, _paint);
  }
image.png

繪制圓角矩形drawDRRect

class MyPainter extends CustomPainter {
  
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.stroke //繪畫風格,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
     //用Rect構(gòu)建一個邊長50,中心點坐標為100,100的矩形
    Rect rect = Rect.fromCircle(center: Offset(140.0, 50.0), radius: 50.0);
    //根據(jù)上面的矩形,構(gòu)建一個圓角矩形
    RRect rrect = RRect.fromRectAndRadius(rect, Radius.circular(20.0));
    canvas.drawRRect(rrect, _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return null;
  }
}
image.png

繪制路徑drawPath

繪制路徑攀芯,首先需要一個要繪制的路徑path屯断,然后就是這個paint了。

方法名            作用
moveTo    將路徑起始點移動到指定的位置
relativeMoveTo    相對于當前位置移動到
lineTo    從當前位置連接指定點
relativeLineTo    相對當前位置連接到
arcTo    曲線
conicTo    貝塞爾曲線
add**    添加其他圖形侣诺,如addArc殖演,在路徑是添加圓弧
contains    路徑上是否包括某點
transfor    給路徑做matrix4變換
combine    結(jié)合兩個路徑
close    關(guān)閉路徑,連接路徑的起始點
reset    重置路徑年鸳,恢復到默認狀態(tài)
class MyPainter extends CustomPainter {
  
  ///[定義畫筆]
  Paint _paint = Paint()
  ..color = Colors.blueAccent //畫筆顏色
  ..strokeCap = StrokeCap.round//畫筆筆觸類型
  ..isAntiAlias = true //是否啟動抗鋸齒
  ..style = PaintingStyle.stroke //繪畫風格趴久,默認為填充
  ..strokeWidth = 5.0; //畫筆的寬度

  @override
  void paint(Canvas canvas, Size size) {
      
   //新建了一個path,然后將路徑起始點移動到坐標(100,100)的位置
    Path path = new Path()..moveTo(100.0, 100.0);
    path.lineTo(200.0, 200.0);
    canvas.drawPath(path, _paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return null;
  }
}

繪制多個路徑

@override
  void paint(Canvas canvas, Size size) {
      
   Path path = new Path()..moveTo(100.0, 100.0);

    path.lineTo(200.0, 200.0);
    path.lineTo(100.0, 300.0);
    path.lineTo(150.0, 350.0);
    path.lineTo(150.0, 500.0);
    
    canvas.drawPath(path, _paint);
  }
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市搔确,隨后出現(xiàn)的幾起案子彼棍,更是在濱河造成了極大的恐慌,老刑警劉巖膳算,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件座硕,死亡現(xiàn)場離奇詭異,居然都是意外死亡涕蜂,警方通過查閱死者的電腦和手機华匾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來机隙,“玉大人蜘拉,你說我怎么就攤上這事萨西。” “怎么了诸尽?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵原杂,是天一觀的道長。 經(jīng)常有香客問我您机,道長穿肄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任际看,我火速辦了婚禮咸产,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘仲闽。我一直安慰自己脑溢,他們只是感情好,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布赖欣。 她就那樣靜靜地躺著屑彻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪顶吮。 梳的紋絲不亂的頭發(fā)上社牲,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天,我揣著相機與錄音悴了,去河邊找鬼搏恤。 笑死,一個胖子當著我的面吹牛湃交,可吹牛的內(nèi)容都是我干的熟空。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼搞莺,長吁一口氣:“原來是場噩夢啊……” “哼息罗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起腮敌,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤阱当,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后糜工,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體弊添,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年捌木,在試婚紗的時候發(fā)現(xiàn)自己被綠了油坝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖澈圈,靈堂內(nèi)的尸體忽然破棺而出彬檀,到底是詐尸還是另有隱情,我是刑警寧澤瞬女,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布窍帝,位于F島的核電站,受9級特大地震影響诽偷,放射性物質(zhì)發(fā)生泄漏坤学。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一报慕、第九天 我趴在偏房一處隱蔽的房頂上張望深浮。 院中可真熱鬧,春花似錦眠冈、人聲如沸飞苇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽布卡。三九已至,卻和暖如春雇盖,著一層夾襖步出監(jiān)牢的瞬間羽利,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工刊懈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人娃闲。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓虚汛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親皇帮。 傳聞我的和親對象是個殘疾皇子卷哩,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容