Flutter 貝塞爾曲線切割


現在人們對於網站的美感要求是越來越高了,所以很多布局需要優美的曲線設計。當然最簡單的辦法是作一個PNG的透明圖片,然后外邊放一個Container.但其內容如果本身就不是圖片,只是容器,這種放入圖片的做法會讓包體變大。其實我們完全可以使用貝塞爾曲線進行切割。

ClipPath 路徑裁切控件

clipPath控件可以把其內部的子控件切割,它有兩個主要屬性(參數):

  • child :要切割的元素,可以是容器,圖片.....
  • clipper : 切割的路徑,這個要和CustomClipper對象配合使用。
class CurvePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('貝塞爾曲線切割')),
      body: Column(
        children: <Widget>[
          ClipPath( //路徑裁切組件
            clipper: BottomClipper(), //路徑
            child: Container(
              color: Colors.deepOrangeAccent,
              height: 200.0,
            ),
          ),
        ],
      ),
    );
  }
}

Scaffold里放置了一個列容器,然后把ClipPath控件放到了里邊,ClipPath的子元素是一個容器控件ContainerBootomClipper是我們自定義的一個對象,里邊主要就是切割的路徑。

CustomClipper 裁切路徑

我們主要的貝塞爾曲線路徑就寫在getClip方法里,它返回一段路徑。

一個二階的貝塞爾曲線是需要控制點和終點的,控制點就像一塊磁鐵,把直線吸引過去,形成一個完美的弧度,這個弧度就是貝塞爾曲線了。

我們先來熟悉一下裁切路徑和貝塞爾曲線,作一個最簡單的貝塞爾曲線出來。

全部代碼如下:

import 'package:flutter/material.dart';

class CustomClipperDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false, //去掉debug圖標
      theme: ThemeData(
        primarySwatch: Colors.red
      ),
      home: CurvePage(),
    );
  }
}

class CurvePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('貝塞爾曲線切割')),
      body: Column(
        children: <Widget>[
          ClipPath( //路徑裁切組件
            clipper: BottomClipper(), //路徑
            child: Container(
              color: Colors.deepOrangeAccent,
              height: 200.0,
            ),
          ),
        ],
      ),
    );
  }
}

class BottomClipper extends CustomClipper<Path>{

  @override
  Path getClip(Size size){
    var path = Path();
    path.lineTo(0, 0); //第1個點
    path.lineTo(0, size.height-50.0); //第2個點
    var firstControlPoint = Offset(size.width/2, size.height);
    var firstEdnPoint = Offset(size.width, size.height-50.0);
    path.quadraticBezierTo(
      firstControlPoint.dx, 
      firstControlPoint.dy, 
      firstEdnPoint.dx, 
      firstEdnPoint.dy
    );
    path.lineTo(size.width, size.height-50.0); //第3個點
    path.lineTo(size.width, 0); //第4個點

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

波浪形式的貝塞爾曲線

在上面代碼的基礎上修改為波浪式的貝塞爾曲線,波浪形式的只要把裁切變成兩個對稱的貝塞爾曲線就可以實現了。

代碼如下:

//曲線路徑
class BottomClipper extends CustomClipper<Path>{
  @override
  Path getClip(Size size){
    var path = Path(); //定義路徑
    //path.lineTo(0, 0); //第1個點
    //path.lineTo(0, size.height-50.0); //第2個點
    //var firstControlPoint = Offset(size.width/2, size.height); //第一段曲線控制點
    //var firstEdnPoint = Offset(size.width, size.height-50.0); //第一段曲線結束點
    //path.quadraticBezierTo( //形成曲線
    //  firstControlPoint.dx, 
    //  firstControlPoint.dy, 
    //  firstEdnPoint.dx, 
    //  firstEdnPoint.dy
    //);
    //path.lineTo(size.width, size.height-50.0); //第3個點
    //path.lineTo(size.width, 0); //第4個點

    //波浪曲線路徑
    path.lineTo(0, 0); //第1個點
    path.lineTo(0, size.height - 40.0); //第2個點
    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 secondControlPoint = Offset(size.width/4*3, size.height-90); //第二段曲線控制點
    var secondEndPoint = Offset(size.width, size.height-40); //第二段曲線結束點
    path.quadraticBezierTo( //形成曲線
      secondControlPoint.dx, 
      secondControlPoint.dy, 
      secondEndPoint.dx, 
      secondEndPoint.dy);
    
    path.lineTo(size.width, size.height-40);
    path.lineTo(size.width, 0);

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM