亲宝软件园·资讯

展开

Android利用ShaderMask实现花里胡哨的文字特效

岛上码农 人气:0

前言

我们的 App 大部分时候的文字都是一种颜色,实际上,文字的颜色也可以多姿多彩。我们今天就来介绍一个能够轻松实现文字渐变色的组件 —— ShaderMaskShaderMask 能够构建一个着色器(shader),然后覆盖(mask)到它的子组件上,从而改变子组件的颜色。

ShaderMask 实现渐变色文字

ShaderMask 的构造函数定义如下。

const ShaderMask({
  Key? key,
  required this.shaderCallback,
  this.blendMode = BlendMode.modulate,
  Widget? child,
})

其中关键的参数是 shaderCallback回调方法,通过 回调方法可以构建一个着色器来为子组件着色,典型的做法是使用 Gradient 的子类(如 LinearGradientRadialGradial)来创建着色器。blendMode 参数则用于设置着色的方式。 因此,我们可以利用LinearGradient来实现渐变色文字,示例代码如下,其中 blendMode 选择为 BlendMode.srcIn 是忽略子组件原有的颜色,使用着色器来对子组件着色。

ShaderMask(
  shaderCallback: (rect) {
    return LinearGradient(
      begin: Alignment.centerLeft,
      end: Alignment.centerRight,
      colors: [
        Colors.blue,
        Colors.green[300]!,
        Colors.orange[400]!,
        Colors.red,
      ],
    ).createShader(rect);
  },
  blendMode: BlendMode.srcIn,
  child: const Text(
    '岛上码农',
    style: TextStyle(
      fontSize: 36.0,
      fontWeight: FontWeight.bold,
    ),
  ),
),

实现效果如下图。

实际上,不仅仅能够对文字着色,还可以对图片着色,比如我们使用一个 Row 组件在文字前面增加一个Image 组件,可以实现下面的效果。

让渐变色动起来

静态的渐变色着色还不够,Gradient 还有个 transform 来实现三维空间变换的渐变效果,我们可以利用这个参数和动画组件实现动画效果,比如下面这样。

这里其实就是使用了动画控制 transform 实现横向平移。由于 transform 是一个 GradientTransform 类,实现这样的效果需要定义一个GradientTransform子类,如下所示。

@immutable
class SweepTransform extends GradientTransform {
  const SweepTransform(this.dx, this.dy);

  final double dx;
  final double dy;

  @override
  Matrix4 transform(Rect bounds, {TextDirection? textDirection}) {
    return Matrix4.identity()..translate(dx, dy);
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) {
      return true;
    }
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is SweepTransform && other.dx == dx && other.dy == dy;
  }

  @override
  int get hashCode => dx.hashCode & dy.hashCode;
}

然后通过 Animation 动画对象的值控制渐变色平移的距离就可以实现渐变色横向扫过的效果了,代码如下所示。

ShaderMask(
  shaderCallback: (rect) {
    return LinearGradient(
      begin: Alignment.centerLeft,
      end: Alignment.centerRight,
      colors: [
        Colors.blue,
        Colors.green[300]!,
        Colors.orange[400]!,
        Colors.red,
      ],
      transform: SweepTransform(
          (_animation.value - 0.5) * rect.width, 0.0),
    ).createShader(rect);
  },
  blendMode: BlendMode.srcIn,
  child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      Image.asset(
        'images/logo.png',
        scale: 2,
      ),
      const Text(
        '岛上码农',
        style: TextStyle(
          fontSize: 36.0,
          fontWeight: FontWeight.bold,
        ),
      ),
    ],
  ),
),

图片填充

除了使用渐变色之外,我们还可以利用 ImageShader 使用图片填充文字,实现一些其他的文字特效,比如用火焰图片作为背景,让文字看起来像燃烧了一样。

实现的代码如下,其中动效是通过 ImageShader 的构造函数的第4个参数的矩阵matrix4运算实现的,相当于是让填充图片移动来实现火焰往上升的效果。

ShaderMask(
  shaderCallback: (rect) {

    return ImageShader(
        fillImage,
        TileMode.decal,
        TileMode.decal,
        (Matrix4.identity()
              ..translate(-20.0 * _animation.value,
                  -150.0 * _animation.value))
            .storage);
  },
  blendMode: BlendMode.srcIn,
  child: Row(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      Image.asset(
        'images/logo.png',
        scale: 2,
      ),
      const Text(
        '岛上码农',
        style: TextStyle(
          fontSize: 36.0,
          fontWeight: FontWeight.bold,
        ),
      ),
    ],
  ),
)

总结

本篇介绍了 ShaderMask 组件的应用,通过 ShaderMask 组件我们可以对子组件进行着色,从而改变子组件原来的颜色,实现如渐变色填充、图片填充等效果。本篇完整源码已提交至:实用组件相关源码

加载全部内容

相关教程
猜你喜欢
用户评论