1. 程式人生 > 實用技巧 >Flutter 貝塞爾曲線實現案例

Flutter 貝塞爾曲線實現案例

前言:

各位同學大家好,有段時間沒有給大家更新文章了,趁著今天有時間我們就給大家分享一個flutter的貝塞爾曲線的繪製的案例,希望能幫助到各位同學的學習和工作,那麼廢話不多說我們正式開始 。

準備工作 :

需要安裝flutter的開發環境:大家可以去看看之前的教程:
1 win系統flutter開發環境安裝教程:https://www.jianshu.com/p/152447bc8718
2 mac系統flutter開發環境安裝教程:https://www.jianshu.com/p/bad2c35b41e3

效果圖:


具體實現:

普通貝塞爾曲線

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: Column(
        children: [
          ClipPath(
           clipper: BottomClippertest(),
            child: Container(
              color: Colors.deepOrangeAccent,
              height: 200,
            ),
          )
        ],
      ),
    );
  }

我們這邊寫了ClipPath 來處理我們貝塞爾曲線的繪製 ClipPath 裡面我們嵌套了一個 Container 盒子元件設定高度200 寬度撐滿螢幕 然後我們來處理ClipPath 元件裡面的 clipper 熟悉

class  BottomClippertest extends CustomClipper<Path>{
  @override
  Path getClip(Size size) {
    var path=Path();
    path.lineTo(0, 0); //第一個點
    path.lineTo(0, size.height-60);//第二個點
    var firstControlPoint=Offset(size.width/2, size.height);  //曲線開始點
    var firstendPoint=Offset(size.width, size.height-60); // 曲線結束點
    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstendPoint.dx, firstendPoint.dy);
    path.lineTo(size.width, size.height-60); //第四個點
    path.lineTo(size.width,0);  // 第五個點
    return path;
  }

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}

我們這邊寫了一個 BottomClippertest 類繼承與 CustomClipper 然後重寫了getClip 和 shouldReclip 方法 ,shouldReclip 方法我們返回 false 在 getClip 方法中我們建立 path物件

 var path=Path();

然後繪製貝塞爾曲線需要的 一些節點 如上圖話的5個點和 貝塞爾曲線的需要的開始點和結束點 最後我們返回一個 path物件即可
完整程式碼:

import 'package:flutter/material.dart';
/**
 *
 * 建立人:xuqing
 * 建立時間:2020年11月14日16:28:54
 * 類說明: 普通貝塞爾曲線
 *
 *
 */
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);
  @override
  _MyHomePageState createState() {
    return _MyHomePageState();
  }
}
class _MyHomePageState extends State<MyHomePage> {
  @override
  void initState() {
    super.initState();
  }
  @override
  void dispose() {
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: Column(
        children: [
          ClipPath(
           clipper: BottomClippertest(),
            child: Container(
              color: Colors.deepOrangeAccent,
              height: 200,
            ),
          )
        ],
      ),
    );
  }
}
class  BottomClippertest extends CustomClipper<Path>{
  @override
  Path getClip(Size size) {
    var path=Path();
    path.lineTo(0, 0); //第一個點
    path.lineTo(0, size.height-60);//第二個點
    var firstControlPoint=Offset(size.width/2, size.height);  //曲線開始點
    var firstendPoint=Offset(size.width, size.height-60); // 曲線結束點
    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstendPoint.dx, firstendPoint.dy);
    path.lineTo(size.width, size.height-60); //第四個點
    path.lineTo(size.width,0);  // 第五個點
    return path;
  }
  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}

波浪形貝塞爾曲線實現:

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: Column(
        children: [
          ClipPath(
            clipper: BottomClipper(),
            child: Container(
              color: Colors.blue,
              height: 200,
            ),
          )
        ],
      ),
    );
  }
}

我們很上面的普通的貝塞爾曲線一樣 我寫了一個 `ClipPath 元件 裡面巢狀一個 Container 元件高度200 寬度撐滿螢幕 我們重點看一下 clipper 屬性的實現:


class  BottomClipper extends CustomClipper<Path>{
  @override
  Path getClip(Size size) {
    var path=Path();
    path.lineTo(0, 0);
    path.lineTo(0, size.height-40);
    var firstControlPoint=Offset(size.width/4, size.height);
    var firstendPoint=Offset(size.width/2.25, size.height-30);
    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstendPoint.dx, firstendPoint.dy);
    var  secondConttorPoint=Offset(size.width/4*3, size.height-90);
    var  secondendPoint=Offset(size.width, size.height-40);
    path.quadraticBezierTo(secondConttorPoint.dx, secondConttorPoint.dy,
        secondendPoint.dx, secondendPoint.dy);
    path.lineTo(size.width, size.height-40);
    path.lineTo(size.width,0);
    return path;
  }
  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}

同上我們寫了一個BottomClipper 類繼承 CustomClipper 類 重寫getClip 方法和 shouldReclip ,shouldReclip 返回 false 重點是getClip 方法裡面 我們建立 path物件

var path=Path();

這個波浪形的貝塞爾曲線我們有2個控制點 分別是在螢幕寬度1/4和螢幕寬度按3/4 處

 var firstControlPoint=Offset(size.width/4, size.height);  //第一個控制點起始點
    var firstendPoint=Offset(size.width/2.25, size.height-30);//第一個控制結束點
    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
        firstendPoint.dx, firstendPoint.dy);
    var  secondConttorPoint=Offset(size.width/4*3, size.height-90); // 第二個控制點起始點
    var  secondendPoint=Offset(size.width, size.height-40); // 第二個控制點結束點
    path.quadraticBezierTo(secondConttorPoint.dx, secondConttorPoint.dy,
        secondendPoint.dx, secondendPoint.dy);

其他的點和上面通普通貝塞爾曲線相同最後我們返回path 即可實現我們的波浪形貝塞爾曲線的繪製了
到此我們最基礎的貝塞爾曲線的繪製就講完了

最後總結:

有時候我們在工作中需要用到一些曲線背景的時候 我們就可以用到貝塞爾曲線繪製加上對應顏色背景即可 這時候有同學就跳出來講 直接一張圖片就搞定了 但是我們加了圖片就會增加資原始檔 也相對應增加flutter專案打包成安裝包的體積,flutter裡面提供好用的api供我們呼叫 我們只需要找到對應節點然後返回路徑去繪製即可。以上的簡單例子只是分享給同學們 ,同學們可以自己研究繪製出更多炫酷的曲線效果,我這邊就不展開講了。 最後希望我的文章能幫助到各位解決問題 ,以後我還會貢獻更多有用的程式碼分享給大家。各位同學如果覺得文章還不錯 ,麻煩給關注和star,小弟在這裡謝過啦 也可以加我個人QQ/微信(1693891473)

專案地址:

碼雲 :https://gitee.com/qiuyu123/flutterbeziercurve

QQ 交流群: