支付寶集五福手畫福字功能(含撤銷操作)用Flutter如何實(shí)現(xiàn)店读?

2022-01-19 16.31.22.gif

今早一覺醒來發(fā)現(xiàn)支付寶一年一度的集五福活動(dòng)又開始了攀芯,其中包含了一個(gè)功能就是手寫福字屯断,還包括撤銷一筆,清除重寫侣诺,保存相冊等殖演,那么使用Flutter應(yīng)該如何實(shí)現(xiàn)這些功能呢?

需求

包含需求的具體有:

  • 界面隨著用戶手指的滑動(dòng)顯示走過軌跡紧武,也就是對應(yīng)的筆畫剃氧。
  • 點(diǎn)擊清空按鈕可以清除所有的筆畫。
  • 點(diǎn)擊撤銷按鈕可以清除上一步畫過的筆畫阻星。
  • 保存所寫的文字樣式到相冊。

實(shí)現(xiàn)思路

顯示筆畫軌跡

使用Listener組件對用戶手指落下、滑動(dòng)和收起的動(dòng)作進(jìn)行監(jiān)聽妥箕,在onPointerDown,onPointerMove,onPointerUp3個(gè)監(jiān)聽方法中返回的PointerMoveEvent對象包含了手指所在的位置坐標(biāo)偏移量localPosition滥酥,用戶每次滑動(dòng)時(shí)都會記錄下軌跡經(jīng)過的坐標(biāo)點(diǎn),這些坐標(biāo)點(diǎn)連接起來就是一條線畦幢。其次坎吻,再配合使用CustomPainter進(jìn)行畫布自繪,將所有劃過的點(diǎn)的連接成線使用畫筆繪制在界面上即可宇葱。

搜集坐標(biāo)點(diǎn):

Listener(
  child: Container(
    alignment: Alignment.center,
    color: Colors.transparent,
    width: double.infinity,
    height: MediaQuery.of(context).size.height,
  ),
  onPointerDown: (PointerDownEvent event) {
    setState(() {
      
    });
  },
  onPointerMove: (PointerMoveEvent event) {
    setState(() {
      
    });
  },
  onPointerUp: (PointerUpEvent event) {
    setState(() {
      
    })瘦真;
  },
),

繪制:

@override
void paint(Canvas canvas, Size size) {
  myPaint.strokeCap = StrokeCap.round;
  myPaint.strokeWidth = 15.0;
  if (lines.isEmpty) {
    canvas.drawPoints(PointMode.polygon, [Offset.zero, Offset.zero], myPaint);
  } else {
    for (int k = 0; k < lines.length; k++) {
      for (int i = 0; i < lines[k].length - 1; i++) {
        if (lines[k][i] != Offset.zero && lines[k][i + 1] != Offset.zero) {
          canvas.drawLine(lines[k][i], lines[k][i + 1], myPaint);
        }
      }
    }
  }
}

撤銷與清空

2022-01-19 16.27.29.gif

看到上面的代碼有的人可能會比較疑惑,繪制時(shí)為什么這么復(fù)雜黍瞧,還出現(xiàn)了雙重循環(huán)诸尽。這就和撤銷功能有關(guān)了,先假設(shè)不需要撤銷功能印颤,其實(shí)我們就可以直接把所有筆畫的點(diǎn)連接到一起進(jìn)行繪制就可以了您机,但是一旦引入了撤銷功能,就要記錄每一筆筆畫年局,福字筆畫是13畫际看,那么理論上是需要記錄13個(gè)筆畫的,才能保證每次撤銷時(shí)都能正常退回上一次畫過的筆跡矢否,所以第一反應(yīng)就是使用集合將每一次筆畫記錄下來仲闽。而上面也說了每一個(gè)筆畫其實(shí)也是多個(gè)坐標(biāo)點(diǎn)的集合,所以所有筆畫就是一個(gè)坐標(biāo)點(diǎn)集合的集合僵朗,即:

/// 所有筆畫劃線集合
List<List<Offset>> _lines = [];

另外蔼囊,也不難想到,我們可以輕易通過手指按下和手指手指的方法回調(diào)來區(qū)分筆畫開始和結(jié)束衣迷。在兩個(gè)方法中進(jìn)行筆畫的add和更新畏鼓。

onPointerDown: (PointerDownEvent event) {
  setState(() {
    _event = event;
    _points.add(_event?.localPosition ?? Offset.zero);
    _lines.add(_points);
  });
},
onPointerMove: (PointerMoveEvent event) {
  setState(() {
    _event = event;
    _points.add(_event?.localPosition ?? Offset.zero);
    _lines.last = _points;
  });
},
onPointerUp: (PointerUpEvent event) {
  setState(() {
    _event = event;
    _points.add(Offset.zero);
    _lines.last = _points;
  });
  _points = [];
},

而前面說的雙重遍歷這時(shí)也比較好理解了:

  • 第一層循環(huán)是遍歷所有的筆畫,遍歷次數(shù)就是福字的筆畫數(shù)壶谒。
  • 第二層循環(huán)是每一個(gè)筆畫包括的好多個(gè)坐標(biāo)點(diǎn)云矫,遍歷出來使用drawLine方法繪制到界面上形成一條線。
    這樣在進(jìn)行撤銷操作時(shí),調(diào)用list的removeLast方法移除最后一項(xiàng)再刷新界面就能實(shí)現(xiàn)退回一筆的效果了汗菜,清空就是清空筆畫集合让禀。

保存到相冊

保存相冊主要是引入了兩個(gè)插件庫:permission_handlerimage_gallery_saver,一個(gè)用來獲取存儲權(quán)限陨界,一個(gè)用來保存到相冊巡揍。
使用RepaintBoundary組件將畫布包裹起來,并指定key菌瘪,在點(diǎn)擊保存時(shí)按順序調(diào)用如下方法先獲取截圖后保存即可:

RenderRepaintBoundary boundary =
    key.currentContext!.findRenderObject() as RenderRepaintBoundary;
var image = await boundary.toImage(pixelRatio: 3.0);
ByteData? byteData = await image.toByteData(format: ImageByteFormat.png);
_postBytes = byteData?.buffer.asUint8List();
var result = await ImageGallerySaver.saveImage(_postBytes!);

完整代碼與demo下載

github地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腮敌,一起剝皮案震驚了整個(gè)濱河市阱当,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌糜工,老刑警劉巖弊添,帶你破解...
    沈念sama閱讀 216,402評論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異捌木,居然都是意外死亡油坝,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評論 3 392
  • 文/潘曉璐 我一進(jìn)店門刨裆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澈圈,“玉大人,你說我怎么就攤上這事帆啃∷才” “怎么了?”我有些...
    開封第一講書人閱讀 162,483評論 0 353
  • 文/不壞的土叔 我叫張陵链瓦,是天一觀的道長拆魏。 經(jīng)常有香客問我,道長慈俯,這世上最難降的妖魔是什么渤刃? 我笑而不...
    開封第一講書人閱讀 58,165評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮贴膘,結(jié)果婚禮上卖子,老公的妹妹穿的比我還像新娘。我一直安慰自己刑峡,他們只是感情好洋闽,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著突梦,像睡著了一般诫舅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宫患,一...
    開封第一講書人閱讀 51,146評論 1 297
  • 那天刊懈,我揣著相機(jī)與錄音,去河邊找鬼娃闲。 笑死虚汛,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的皇帮。 我是一名探鬼主播卷哩,決...
    沈念sama閱讀 40,032評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼属拾!你這毒婦竟也來了将谊?” 一聲冷哼從身側(cè)響起冷溶,我...
    開封第一講書人閱讀 38,896評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓢娜,沒想到半個(gè)月后挂洛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體礼预,經(jīng)...
    沈念sama閱讀 45,311評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眠砾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了托酸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褒颈。...
    茶點(diǎn)故事閱讀 39,696評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖励堡,靈堂內(nèi)的尸體忽然破棺而出谷丸,到底是詐尸還是另有隱情,我是刑警寧澤应结,帶...
    沈念sama閱讀 35,413評論 5 343
  • 正文 年R本政府宣布刨疼,位于F島的核電站,受9級特大地震影響鹅龄,放射性物質(zhì)發(fā)生泄漏揩慕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評論 3 325
  • 文/蒙蒙 一扮休、第九天 我趴在偏房一處隱蔽的房頂上張望迎卤。 院中可真熱鬧,春花似錦玷坠、人聲如沸蜗搔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽樟凄。三九已至,卻和暖如春兄渺,著一層夾襖步出監(jiān)牢的瞬間缝龄,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評論 1 269
  • 我被黑心中介騙來泰國打工溶耘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留二拐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評論 2 368
  • 正文 我出身青樓凳兵,卻偏偏與公主長得像百新,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子庐扫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評論 2 353

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

  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫饭望、插件仗哨、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,093評論 4 62
  • 轉(zhuǎn)載自:https://github.com/Tim9Liu9/TimLiu-iOS 目錄 UI下拉刷新模糊效果A...
    袁俊亮技術(shù)博客閱讀 11,921評論 9 105
  • 嗯哼嗯哼蹦擦擦~~~ 轉(zhuǎn)載自:https://github.com/Tim9Liu9/TimLiu-iOS 目錄 ...
    philiha閱讀 4,870評論 0 6
  • 16宿命:用概率思維提高你的勝算 以前的我是風(fēng)險(xiǎn)厭惡者,不喜歡去冒險(xiǎn)铅辞,但是人生放棄了冒險(xiǎn)厌漂,也就放棄了無數(shù)的可能。 ...
    yichen大刀閱讀 6,046評論 0 4
  • 公元:2019年11月28日19時(shí)42分農(nóng)歷:二零一九年 十一月 初三日 戌時(shí)干支:己亥乙亥己巳甲戌當(dāng)月節(jié)氣:立冬...
    石放閱讀 6,877評論 0 2