Flutter自定义控件-RenderObject-Canvas绘制内阴影(InnerShadow)|flutter动画(准备)

Flutter自定义控件绘制内阴影

详细介绍视频地址链接:Flutter自定义控件-RenderObject-Canvas绘制内阴影(InnerShadow)|flutter动画(准备)
Flutter3D书本翻页视频地址链接:Flutter Animation 3D仿真书本翻页动画效果
效果图:

在这里插入图片描述

主要代码
InnerShadowPage
import 'package:flutter/material.dart';
import 'package:flutter_demo/components/inner_shadow.dart';

class InnerShadowPage extends StatelessWidget {
  const InnerShadowPage({Key? key}) : super(key: key);

  Color _shadowColor() => const Color.fromRGBO(222, 234, 252, 1);

  Widget _textWidget() =>
      const Text('data', style: TextStyle(fontSize: 36, color: Colors.black));

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: const Text('InnerShadow'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: <Widget>[
            Container(
              width: 200,
              height: 200,
              clipBehavior: Clip.hardEdge,
              decoration:
                  BoxDecoration(borderRadius: BorderRadius.circular(20)),
              child: Container(
                padding: const EdgeInsets.all(20),
                decoration: BoxDecoration(
                  color: _shadowColor(),
                  borderRadius: BorderRadius.circular(20),
                ),
                child: Container(
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(20),
                    boxShadow: const [
                      BoxShadow(
                        color: Colors.white,
                        blurRadius: 10,
                        spreadRadius: 20,
                      ),
                    ],
                  ),
                  child: _textWidget(),
                ),
              ),
            ),
            InnerShadow(
              blur: 6,
              shadowColor: _shadowColor(),
              offset: const Offset(2, 2),
              child: Container(
                width: 200,
                height: 200,
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(20),
                ),
                child: _textWidget(),
              ),
            )
          ],
        ),
      ),
    );
  }
}

自定义InnerShadow控件
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

// https://pub.flutter-io.cn/packages/sums_inner

class InnerShadow extends SingleChildRenderObjectWidget {
  const InnerShadow({
    Key? key,
    this.blur = 10,
    this.shadowColor = Colors.black45,
    this.offset = const Offset(10, 10),
    required Widget child,
  }) : super(key: key, child: child);

  final double blur;
  final Color shadowColor;
  final Offset offset;

  
  RenderObject createRenderObject(BuildContext context) {
    final RenderInnerShadow renderObject = RenderInnerShadow();
    updateRenderObject(context, renderObject);
    return renderObject;
  }

  
  void updateRenderObject(
      BuildContext context, RenderInnerShadow renderObject) {
    renderObject
      ..shadowColor = shadowColor
      ..blur = blur
      ..dx = offset.dx
      ..dy = offset.dy;
  }
}

class RenderInnerShadow extends RenderProxyBox {
  late double blur;
  late Color shadowColor;
  late double dx;
  late double dy;

  
  void paint(PaintingContext context, Offset offset) {
    if (child == null) return;
    final Rect rectOuter = offset & size;
    final Rect rectInner = Rect.fromLTWH(
      offset.dx,
      offset.dy,
      size.width - dx,
      size.height - dy,
    );
    final Canvas canvas = context.canvas..saveLayer(rectOuter, Paint());
    context.paintChild(child!, offset);
    final Paint shadowPaint = Paint()
      ..blendMode = BlendMode.srcATop
      ..colorFilter = ColorFilter.mode(shadowColor, BlendMode.srcOut)
      ..imageFilter = ImageFilter.blur(sigmaX: blur, sigmaY: blur);
    canvas
      ..saveLayer(rectOuter, shadowPaint)
      ..saveLayer(rectInner, Paint())
      ..translate(dx, dy);
    context.paintChild(child!, offset);
    context.canvas
      ..restore()
      ..restore()
      ..restore();
  }
}

混合模式

List blendMode = [
BlendMode.srcATop,
BlendMode.srcOut,
BlendMode.clear,
BlendMode.src,
BlendMode.dst,
BlendMode.srcOver,
BlendMode.dstOver,
BlendMode.srcIn,
BlendMode.dstIn,
BlendMode.dstOut,
BlendMode.dstATop,
BlendMode.xor,
BlendMode.plus,
BlendMode.modulate,
BlendMode.screen,
BlendMode.overlay,
BlendMode.darken,
BlendMode.lighten,
BlendMode.colorDodge,
BlendMode.colorBurn,
BlendMode.hardLight,
BlendMode.softLight,
BlendMode.difference,
BlendMode.exclusion,
BlendMode.multiply,
BlendMode.hue,
BlendMode.saturation,
BlendMode.color,
BlendMode.luminosity,
];

内容涉及到的混合模式(先绘制的是目标图像,后绘制的是源图像)
BlendMode.srcOut

显示源图像,但仅显示两个图像不重叠的位置。目标图像不会渲染,仅将其视为蒙版。目标的颜色通道被忽略,只有不透明度有效

BlendMode.srcATop

源图和目标图相交处绘制原图,不相交绘制目标图

BlendMode.color

取源图像的色调和饱和度,然后取目标图像的亮度

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值