3

我似乎无法用 png ui.Image 掩盖小部件并保持透明度。透明(不可见)像素呈现黑色。

在我的自定义画家上绘制蒙版 png 图像时,我尝试使用 BlendMode srcIn,预期的行为是被果冻豆形状掩盖的彩色背景。然而,透明(应该删除)像素被渲染为黑色(见附图)。这是一个错误吗?还是我错过了什么?我也知道 ImageShader 选项,但它缺乏我在我的应用程序中需要的灵活性。在屏幕之间转换并应用英雄动画时,画布会按预期呈现一小段时间。

任何帮助都感激不尽 :)

应用程序屏幕截图 应用程序打印屏幕

蒙版图像 蒙版图像

背景图片 背景图片

预期的 预期的

import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  ui.Image mask;

  initState() {
    super.initState();

    load('https://img.pngio.com/shape-png-free-download-free-shapes-png-493_315.png')
        .then((image) {
      setState(() {
        mask = image;
      });
    });
  }

  Future<Uint8List> _loadFromUrl(String url) async {
    final response = await http.get(url);

    if (response.statusCode >= 200 && response.statusCode < 300) {
      return response.bodyBytes;
    } else {
      return null;
    }
  }

  Future<ui.Image> load(String asset) async {
    var a = await _loadFromUrl(asset);
    ui.Codec codec = await ui.instantiateImageCodec(a);
    ui.FrameInfo fi = await codec.getNextFrame();
    return fi.image;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(
        children: <Widget>[
          Positioned(
            top: 10,
            left: 100,
            child: Hero(
                tag: 'imageHero',
                child: Container(
                  width: 200,
                  height: 200,
                  child: CustomPaint(
                    foregroundPainter: LayerPainter(mask: mask),
                    child: Image.network(
                        "https://www.thecommercialhotel.com/wp-content/uploads/2015/11/Live-Lounge-BG.jpg",
                        fit: BoxFit.fill),
                  ),
                )),
          )
        ],
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          Navigator.push(context,
              MaterialPageRoute(builder: (BuildContext context) {
            return Page2(mask: mask,);
          }));
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

class LayerPainter extends CustomPainter {
  ui.Image mask;

  LayerPainter({@required this.mask}) {}

  @override
  void paint(Canvas canvas, Size size) {
    if (mask != null) {
      canvas.drawImageRect(
          mask,
          Rect.fromLTWH(0, 0, mask.width.toDouble(), mask.height.toDouble()),
          Rect.fromLTWH(0, 0, size.width, size.height),
          new Paint()..blendMode = BlendMode.dstIn);
    }
  }

  @override
  bool shouldRepaint(LayerPainter oldDelegate) {
    return oldDelegate.mask != this.mask;
  }
}

class Page2 extends StatelessWidget {

  final ui.Image mask;

  Page2({ @required this.mask});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Stack(
        children: <Widget>[
          Positioned(
            top: 400,
            left: 100,
            child: Hero(
                tag: 'imageHero',
                child: Container(
                  width: 200,
                  height: 200,
                  child: CustomPaint(
                    foregroundPainter: LayerPainter(mask: mask),
                    child: Image.network(
                        "https://www.thecommercialhotel.com/wp-content/uploads/2015/11/Live-Lounge-BG.jpg",
                        fit: BoxFit.fill),
                  ),
                )),
          )
        ],
      ));
  }
}

4

2 回答 2

3

无法解决 Custom Painter 渲染问题,我最终使用了不同的方法。我只是在单独的画布上渲染蒙版 png,导出 ui.Image 并使用自定义画家绘制它。Thins 使我能够使用 BlendMode.srcIn 并保持透明度。您可以在此博客文章中了解更多信息

于 2019-09-11T07:30:17.563 回答
0

如果没有自定义画家,您可以使用 ShaderMask 和 ImageShader 获得预期的结果。该视频我的存储库将为您提供帮助。

于 2020-04-12T06:35:56.187 回答