今天。。。是一個很是重要的日子-女神節。做爲一名程序員,如何向心儀的人低調而又不失逼格的表達祝福,關係到咱們後半生的幸福,祝福的到位,普通朋友加個字變成女友,女友變成老婆,若是已是老婆了,那麼這個月的零花錢又能多好幾百,想一想都激動。程序員
回到現實,做爲程序員,咱們固然要獨一無二,要不同凡響,要突破天際,要能體現咱們的身份,逼格滿滿,所以咱們要給女神開發一個天上地下、惟吾獨尊的App絕對是你不二的選擇。canvas
廢話很少說,No 圖 No 說話:數組
先來分析一波:微信
首先上面的效果是一直在繪製路徑,當繪製完花和葉子時在對其着色,所以這裏比較難是如何獲取路徑的點座標,只要有點的座標了一個個的畫出來也就實現了上面的效果。ide
那麼如今的重點就是如何獲取點座標,一種方法是人工一個一個的寫,而後調整,這種方法工做量太大了,做爲程序員怎麼能用這種方法呢?怎麼纔可讓程序生成這些座標呢?學習
想一想咱們在監聽手勢(鼠標)時是否是能夠獲取到當前點的座標,移動的時候也能夠獲取到一個移動的路徑座標,所以咱們只須要在屏幕上先加載想要的圖片,而後按照圖片上的路徑移動,是否是就能夠獲取到咱們想要的路徑了啊。動畫
對於任何語言來講均可以按照上面的思路來實現,下面以目前很是火熱的Flutter來實現這個功能。ui
好,首先來加載一張圖片,而後監聽其手勢(鼠標)移動事件,代碼以下:this
Container( width: 400, height: 700, child: GestureDetector( onLongPressStart: (LongPressStartDetails details) { print('${details.localPosition},'); }, onLongPressMoveUpdate: (LongPressMoveUpdateDetails details) { print('${details.localPosition},'); }, onLongPressEnd: (LongPressEndDetails details) { print('${details.localPosition},'); }, child: Image.asset( 'images/123.png', fit: BoxFit.fill, ), ), )
這裏要注意2點:code
咱們把路徑輸出到控制檯,後臺只需將這些座標拷貝到應用程序便可,將這些座標定義爲數組,以下:
static final List<Offset> flowerPoints = [ Offset(182.0, 136.3), Offset(182.7, 135.3), Offset(183.0, 135.3), Offset(183.3, 135.3), ... )
點到路徑獲取到,下面就是繪製了,先繪製紅色的花骨朵,在Flutter中繪製路徑須要繼承CustomPainter類,重寫paint
方法,繪製路徑及填充顏色代碼以下:
@override void paint(Canvas canvas, Size size) { //將花變爲紅色 if (flowerPaths.length >= RoseData.flowerPoints.length) { var path = Path(); for (int i = 0; i < flowerPaths.length; i++) { if (i == 0) { path.moveTo(flowerPaths[i].dx, flowerPaths[i].dy); } else { path.lineTo(flowerPaths[i].dx, flowerPaths[i].dy); } } _paint.style = PaintingStyle.fill; _paint.color = _flowerColor; canvas.drawPath(path, _paint); } //繪製線 _paint.style = PaintingStyle.stroke; _paint.color = _strokeColor; canvas.drawPoints(PointMode.polygon, flowerPaths, _paint); }
這裏要注意只有噹噹花骨朵全部的路徑都繪製完以後才填充顏色,並且要先填充顏色,而後繪製路線,否則路線會被填充顏色覆蓋。
要想有繪製路徑的效果,須要將點依次增長,增長動畫控制器,控制繪製路徑,代碼以下:
AnimationController _controller; Animation<num> _animation; @override void initState() { _controller = AnimationController( duration: Duration(seconds: 10), vsync: this) ..addListener(() { setState(() { _flowerPaths = RoseData.flowerPoints.sublist(0, _animation.value.floor()); }); }); _animation = Tween( begin: 0.0, end: RoseData.flowerPoints.length) .animate(_controller); }
構建UI代碼以下:
@override Widget build(BuildContext context) { Container( width: 400, height: 700, child: CustomPaint( painter: RosePaint(_flowerPaths), ), ) }
RosePaint是自定義的CustomPaint。效果以下:
在最終的填充上發現有一部分沒有填充上,圖中藍色點爲最後一個點,因此須要在增長2個點,綠色和黃色位置的點,把未填充區域填充上。
填充點代碼以下:
static final List<Offset> flowerPoints = [ Offset(182.0, 136.3), Offset(182.7, 135.3), ... Offset(179.3, 301.7), Offset(237.7, 144.7), ];
在繪製線的時候須要將這2個點去掉:
if (flowerPaths.length >= RoseData.flowerPoints.length) { var path = Path(); for (int i = 0; i < flowerPaths.length; i++) { if (i == 0) { path.moveTo(flowerPaths[i].dx, flowerPaths[i].dy); } else { path.lineTo(flowerPaths[i].dx, flowerPaths[i].dy); } } _paint.style = PaintingStyle.fill; _paint.color = _flowerColor; canvas.drawPath(path, _paint); } //繪製線 _paint.style = PaintingStyle.stroke; _paint.color = _strokeColor; //去掉最後2個點,最後2個點爲了繪製紅色 var points = flowerPaths.sublist(0, max(0, flowerPaths.length - 2)); canvas.drawPoints(PointMode.polygon, points, _paint);
花骨朵就行了,其餘的葉子和部位也是同樣的畫法,這裏就不在介紹了,因爲代碼比較多,就不全貼在這裏了,若是須要能夠加我微信。
今天的文章對你們是否有幫助?若是有,請在文章底部留言和點贊,以表示對個人支持,大家的留言、點贊和轉發關注是我持續更新的動力!
本人建立了一個關於Flutter的微信交流羣和「技術人運營本身(吹NB)」交流羣,歡迎您的加入,讓咱們一塊兒學習,一塊兒進步,開始咱們的故事。
添加微信請備註:Flutter(進Flutter交流羣)、吹NB(進吹NB羣)、2(都進)。我但願您備註「2」,生活不止眼前的苟且,還有詩和《遠方》。
微信:mqd_zzy