美文网首页
Flutter 学习 之 线性渐变 (LinearGradien

Flutter 学习 之 线性渐变 (LinearGradien

作者: 半城半离人 | 来源:发表于2023-05-27 12:28 被阅读0次

线性渐变

为了创建一个线性渐变,你需要设置一个起始点和一个方向(指定为一个角度)的渐变效果。并需要设置最少一个起始色和一个终止色 所以colors的参数长度至少为两个

基础语法

如果你之前使用过CSS3的渐变,对于下面的CSS代码一定有所了解:

  background-image: linear-gradient(to right, red , blue);
   background-size: 100% 20px;
/* background-image: linear-gradient(direction, color-stop1, color-stop2, ...);
 */

那么类比Flutter的linearGadient 不难发现两边还是比较相似的

LinearGradient({
    this.begin = Alignment.centerLeft,
    this.end = Alignment.centerRight,
    required super.colors,
    super.stops,
    this.tileMode = TileMode.clamp,
    super.transform,
  }
  • Direction

direction作为角度 需要指定一个角度转换为Flutter中的begin和end
由于Fluter将顶部坐标设置为-1有别于一般坐标轴 使得转换关系如下

名称 角度 位置关系 起始点 终点 图像
toTopCenter 0deg || 360deg 自下而上 (0,1) (0,-1) toCenterTop.png
toBottomCenter 180deg || -180deg 自上而下 (0,-1) (0,1) toCenterBottom.png
toTopRight 45deg || -315deg 左下到右上 (-1,1) (1,-1) toTopRight.png
toBottomLeft 225deg || -135deg 右上到左下 (1,-1) (-1,1) toBottomLeft.png
toRightCenter 90deg || -270deg 自右向左 (0,1) (0,-1) toCenterRight.png
toCenterLeft 270deg || -90deg 自左向右 (0,-1) (0,1) toCenterLeft.png
toBottomRight 135deg || -225deg 左上到右下 (1,-1) (-1,1) toBottomRight.png
toTopLeft 315deg || -45eg 右下到左上 (-1,1) (1,-1) toTopLeft.png

角度换算方法如下

///角度转换后的类
class HcGradientAliment {
  Alignment begin;
  Alignment end;

  HcGradientAliment(
      {this.begin = Alignment.topCenter, this.end = Alignment.bottomCenter});
}
  ///将角度转换成需要的起始位置
  ///[degree] 旋转的角度
  ///[lineWidthThick] 每段宽度
  ///[lineHeightThick] 每段高度
  static HcGradientAliment formatDegree2Aliment(
      {required double degree, lineWidthThick = 1, lineHeightThick = 1}) {
    HcGradientAliment gradientAliment = HcGradientAliment();
    //避免0/0的情况
    degree = degree == 0 ? 360 : degree;
    //将角度转换成0-360;
    degree = (degree + 360) % 360;
    //将角度变成-180-180
    degree = degree > 180 ? degree - 360 : degree;
    //0,90,180,270,360 tan值为0
    //获取y=kx+b中的k 斜率
    double k = degree % 90 == 0 ? 0 : tan(HcNumberUtil.degree2radians(degree));

    //角度与角度绝对值的比为正表示在坐标轴右侧 否则在左侧
    //计算方法 y=tanA*x;
    //如果角度在(0-180]度时,起始角度的X轴为[-1,0];
    double tempX =
        HcNumberUtil.formatNumber(degree == 0 ? 1 : -(degree / degree.abs()));
    // 勾股定理 计算当X轴(角度为负的时候取1,角度为正的时候取-1 )的时候Y轴参数
    //计算方法 y=tanA*x;
    // 因为Aliment坐标轴Y轴顶端为-1与正常的坐标轴相反所以要*-1
    double startY = -HcNumberUtil.formatNumber(tempX * k);
    //计算当Y轴等于1的时候X轴所在位置
    // x=y/tanA;
    //当前角度的绝对值大于90度的 时候y轴坐落在(0,1]之间
    double tempY = (degree.abs() > 90 ? 1 : -1);
    double startX = k == 0 ? 0 : HcNumberUtil.formatNumber(tempY / k);
    // startX = startX.abs() == double.infinity ? 0 : startX;
    //当startY超过1的时候表示x取1的时候 y的值越界所以只能取startX的值
    //当startX超过1的时候表示y取1的时候x越界 所以取startY的值
    if (degree % 180 == 0 || degree != 90 && startX.abs() <= 1) {
      gradientAliment.begin = Alignment(startX, -tempY);
    } else {
      gradientAliment.begin = Alignment(tempX, startY);
    }

    //结束的角度与初始角度呈中心对称
    gradientAliment.end = Alignment(
        -gradientAliment.begin.x * (lineWidthThick * 2 - 1),
        -gradientAliment.begin.y * (lineHeightThick * 2 - 1));
    return gradientAliment;
  }
    ///将角度转换成弧度
  ///[degree] 角度
  static double degree2radians(double degree) {
    return degree * (pi / 180);
  }
    ///简易解决计算精度问题 避免出现0.2+0.1=0.300000000004的情况
  ///[number] 数字
  static double formatNumber(num number) {
    return double.parse(number.toStringAsFixed(2));
  }
  • 控制宽度

在css中是使用 background-size: 100% 20px;控制 宽度与高度
他们的宽高取决于父组件的宽高如果需要宽高的百分比保持相同数值请对应在某一个方向* 父组件的纵横比
在Flutter中则是用起始点和终点之间的距离确定宽高 所以在上面转换角度时有两个选填参数 lineWithThick lineHeightThick 百分制 ( 如果终点坐标x为0时 lineWithThick将不会被作用,反之如果终点坐标y为0时 lineHeightThick亦不会作用)

  • color-stop

colors-stops.png

在css中 color-stop作为一组参数出现在构造中 Flutter 将他们拆分成两个List,但是作用相同 Flutter中需要stops和colors中数量完全匹配

/* css中: */
    linear-gradient(
        to bottom,
        #30e8bf 25%,
        /* 这里的0,是缩写,相当于25% */
        #2a6b7e 0,
        #2a6b7e 50%,
        /* 这里的0,是缩写,相当于50% */
        #ff8235 0
      );
LinearGradient(
        colors: [Color(0xff30e8bf),Color(0xff2a6b7e),Color(0xff2a6b7e),Color(0xffff8235)],
        stops: [0.25,0,0.5,0],
        begin: Alignment.topCenter,
        end: Alignment.bottomCenter,)

上部分代码表示 0-25%是#ff30e8bf到#ff30e8bf(也就是纯色色块) 25%-50% #2a6b7e到2a6b7e 50%-100%#ff8235到#ff8235 为纯色

  • TileMode 平铺模式

Flutter 规定了 四种平铺模式

模式 详细
clamp 复制边缘颜色的平铺
repeated 重复顺序平铺
mirror 重复但是镜像的平铺
decal 区域外为透明色
  • Gradient 与Color无法兼容的情况

Flutter中如果同时在一个decoration中设置Color和gradient则color不会被表达,这时只需要将gradient写到foregroundDecoration即可(将渐变设置为一个前景色)

     Container(
            width: 200,
            height: 100,
            decoration: const BoxDecoration(color: Colors.transparent),
            foregroundDecoration: const BoxDecoration(
              gradient: LinearGradient(
                colors: [
                  Color(0xff30e8bf),
                  Color(0xff2a6b7e),
                  Color(0xff2a6b7e),
                  Color(0xffff8235),
                ],
                stops: [0.25, 0, 0.5, 0],
                begin: Alignment.topCenter,
                end: Alignment.bottomCenter,
              ),
            ),
          ),

应用

  • 做分割线

LinearGradient(
      colors: [color, Colors.transparent],
      stops: [0.5, 0],
      begin: Alignment.centerLeft,
      end: Alignment(-0.8, -0.0),
      tileMode: TileMode.repeated,);
  • 做进度条

    • 做斜条纹的
  LinearGradient(
      colors: [ Colors.purple,Colors.transparent,Colors.transparent],
      stops: [0.4, 0, 0.5],
      begin: Alignment.bottomLeft,
      end: Alignment(-0.9, -0.0),
      tileMode: TileMode.repeated,);
  • 单纯进度
  LinearGradient(
        colors: [color, Colors.transparent],
        stops: [x, 0],
        begin: Alignment.centerLeft,
        end: Alignment.centerRight,
        tileMode: TileMode.decal,);

相关文章

网友评论

      本文标题:Flutter 学习 之 线性渐变 (LinearGradien

      本文链接:https://www.haomeiwen.com/subject/vrpzsdtx.html