47

我正在尝试复制我的设计师为应用程序所做的登录屏幕设计。

背景图像使用 softLight 的 blendMode,关键是它混合的颜色是渐变色。其次实际上有两层不同的渐变(一层紫色渐变,一层蓝色渐变)

原图:

原始图像

最终渐变图像

最终渐变图像

现在我尝试使用 colorBlendMode,例如

Image.asset(
      'assets/pioneer-party.jpg',
      fit: BoxFit.cover,
      color: Color(0xff0d69ff).withOpacity(1.0),
      colorBlendMode: BlendMode.softLight,
    ),

问题是颜色属性只采用单一颜色。

然后我尝试了 BoxDecoration,例如

DecoratedBox(
      decoration: new BoxDecoration(
        color: const Color(0xff7c94b6),
        image: new DecorationImage(
          fit: BoxFit.cover,
          colorFilter: new ColorFilter.mode(Colors.purple.withOpacity(1.0), BlendMode.softLight),
          image: new NetworkImage(
            'http://www.allwhitebackground.com/images/2/2582-190x190.jpg',
          ),
        ),
      ),
    ),

这仍然给我留下了同样的问题。然后我尝试单独堆叠每一层,然后使用渐变来使其看起来接近设计,例如

Image.asset(
      'assets/pioneer-party.jpg',
      fit: BoxFit.cover,
      color: Color(0xff0d69ff).withOpacity(1.0),
      colorBlendMode: BlendMode.softLight,
    ),
    DecoratedBox(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: FractionalOffset.topCenter,
          end: FractionalOffset.bottomCenter,
          colors: [
            Color(0xff0d69ff).withOpacity(0.0),
            Color(0xff0069ff).withOpacity(0.8),
          ],
        ),
      ),
    ),
    DecoratedBox(
      decoration: BoxDecoration(
        gradient: LinearGradient(
          begin: FractionalOffset.topLeft,
          end: FractionalOffset.bottomRight,
          colors: [
            Color(0xff692eff).withOpacity(0.8),
            Color(0xff642cf4).withOpacity(0.8),
            Color(0xff602ae9).withOpacity(0.8),
            Color(0xff5224c8).withOpacity(0.8),
            Color(0xff5e29e5).withOpacity(0.8),
          ],
        stops: [0.0,0.25,0.5,0.75,1.0]
        ),
      ),
    ),

这让我有点接近我想要的,但不完全是我需要的。

有谁知道实现这一目标的方法?

编辑:

我也在考虑将这两个图像混合在一起,但除了使用不透明度或其他东西之外,还没有找到这样做的方法。理想情况下,希望它以原生方式呈现,而不是使用“hacks”来实现它。

4

4 回答 4

75

使用堆栈来获得这种效果非常容易。

   Stack(children: <Widget>[
        Container(
          decoration: BoxDecoration(
            color: Colors.transparent,
            image: DecorationImage(
              fit: BoxFit.fill,
              image: AssetImage(
                'images/bg.jpg',
              ),
            ),
          ),
          height: 350.0,
        ),
        Container(
          height: 350.0,
          decoration: BoxDecoration(
              color: Colors.white,
              gradient: LinearGradient(
                  begin: FractionalOffset.topCenter,
                  end: FractionalOffset.bottomCenter,
                  colors: [
                    Colors.grey.withOpacity(0.0),
                    Colors.black,
                  ],
                  stops: [
                    0.0,
                    1.0
                  ])),
        )
      ]),  

干杯

于 2018-11-06T19:45:53.267 回答
17

你也可以试试这个:

ColorFiltered(
  colorFilter: ColorFilter.mode(Colors.red.withOpacity(0.4), BlendMode.srcOver),
  child: YourWidget(),
) 
于 2019-09-12T19:45:16.780 回答
2

我的解决方案是用 shaderMask 包裹我的图像,这是一个对我有用的例子

ShaderMask(
  shaderCallback: (bounds) {
    return LinearGradient(
      colors: node.badge!.colorsArray,
    ).createShader(bounds);
  },
  child: Image.asset(
    Assets.main_logo,
    height: 27.0,
    fit: BoxFit.cover,
  ),
  blendMode: BlendMode.srcATop,
),

如果您参考 BlendMode 文档https://docs.flutter.io/flutter/dart-ui/BlendMode-class.html,您实际上可以找到您需要 的内容一只忙碌的猫

于 2021-10-28T13:24:24.597 回答
0

编辑

只有const double scale = 2.04015;在浏览器中运行 Flutter 时才有效。对于手机,使用const double scale = 0;

=================================================

聚会迟到了三年半,但我注意到没有一个答案能抓住,甚至不明白想要的效果是什么。因此,让我们首先分析想要的结果,然后对其进行编码。

渐变图

这种效果被称为“渐变映射”,因为单个像素值被映射到基于预定义颜色集的渐变。

让我们来看看。如果输入是灰度图像Color color1 = Colors.blueColor color2 = Colors.purple,则应按以下方式转换单个像素颜色 -

梯度图的视觉表示

在哪里

  • 黑色像素颜色 - 转换为蓝色
  • 白色像素颜色 - 转换为紫色
  • 介于两者之间的颜色 - 转换为介于蓝色和紫色之间的适当颜色

代码

我最初的想法是拍摄一张图像,将其解码为Uint8Listusing getBytes(),处理列表并最终将其编码回 png。虽然这种方法有效,但对于实时用例来说,它的性能还差得很远。

因此,第二种可行的方法是使用颜色矩阵创建效果 -

class GradientMap extends StatelessWidget {

  final Color color1;
  final Color color2;
  final double contrast;
  final ImageProvider imageProvider;

  const GradientMap({
    this.color1 = Colors.white,
    this.color2 = Colors.black,
    this.contrast = 0,
    required this.imageProvider,
    Key? key
  }) : super(key: key);


  ColorFilter grayscaleMatrix() => ColorFilter.matrix([
    0.2126,       0.7152,       0.0722,       0, 0,
    0.2126,       0.7152,       0.0722,       0, 0,
    0.2126,       0.7152,       0.0722,       0, 0,
    contrast-0.4, contrast-0.4, contrast-0.4, 1, 0,
  ]);


  ColorFilter invertMatrix() => const ColorFilter.matrix([
    -1,  0,  0, 0, 255,
     0, -1,  0, 0, 255,
     0,  0, -1, 0, 255,
     0,  0,  0, 1, 0,
  ]);


  ColorFilter tintMatrix () {
    final int r = color2.red;
    final int g = color2.green;
    final int b = color2.blue;

    final double rTint = r / 255;
    final double gTint = g / 255;
    final double bTint = b / 255;

    const double scale = 2.04015; // Use 0 on mobile instead
    const double translate = 1 - scale * 0.5;

    return ColorFilter.matrix(<double>[
      (rTint * scale), (rTint * scale), (rTint * scale), (0), (r * translate),
      (gTint * scale), (gTint * scale), (gTint * scale), (0), (g * translate),
      (bTint * scale), (bTint * scale), (bTint * scale), (0), (b * translate),
      (0            ), (0            ), (0            ), (1), (0            ),
    ]);
  }


  @override
  Widget build(BuildContext context) {
    return Container(
      color: color1,
      child: ColorFiltered(
        colorFilter: tintMatrix(),
        child: ColorFiltered(
          colorFilter: invertMatrix(),
          child: ColorFiltered(
            colorFilter: grayscaleMatrix(),
            child: Image(image: imageProvider)),
        ),
      ),
    );
  }
}

或者,您可以将grayscaleMatrix()和组合invertMatrix()成一个,以消除对第三ColorFiltered()个小部件的需求。

小部件作为输入

  • color1- 打火机Color
  • color2- 越暗Color
  • contrast- doublecolor1 和 color2 之间的混合
  • imageProvider- ImageProvider 例如AssetImage()NetworkImage()

并显示转换后的图像。 在此处输入图像描述

用法

只需按以下方式使用此小部件包装您的 ImageProvider -

GradientMap(
  color1: Color.fromRGBO(158, 80, 254, 1),
  color2: Color.fromRGBO(15, 4, 192, 1),
  contrast: 0,
  imageProvider: NetworkImage("https://i.imgur.com/C5xknx8.png"),
)

缺点

虽然这种方法很有效,但用户无法控制两种输入颜色之间的混合算法。此外,小部件仅将两种颜色作为输入。这消除了使用多色渐变的可能性。

于 2022-01-29T11:20:43.090 回答