如何在Flutter中从图像的一部分创建一个小部件?

mnemlml8  于 2022-11-25  发布在  Flutter
关注(0)|答案(3)|浏览(139)

我有一个图像(蓝色矩形)。我想通过路径(红色三角形)剪切图像的一部分,并创建一个较小的小部件(绿色矩形),显示图像的这一部分,其大小等于剪切路径的边界。我如何在Flutter中做到这一点?

我尝试使用ClipPathCustomClipper<Path>,但我只能创建具有图像大小的小部件。

jaql4c8m

jaql4c8m1#

由于您没有提供任何代码,我假设您希望拥有基于当前子对象小部件。
如果是,您可以尝试IntrinsicWidthIntrinsicHeight小部件。https://api.flutter.dev/flutter/widgets/IntrinsicWidth-class.html
IntrinsicWidgth
创建一个小部件,该小部件将其子级的大小调整为该子级的固有宽度。
此类非常有用,例如,当无限制宽度可用,而您希望将原本会尝试无限扩展的子级改为将其自身调整为更合理的宽度时。
使用此小部件,将根据固有大小使用呈现子对象。

oewdyzsn

oewdyzsn2#

你可以使用CustomPainterdrawAtlas,performant,显示图像的一部分。

wwwo4jvm

wwwo4jvm3#

我找到了这个解决方案:

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

import 'package:flutter/material.dart';

class MyWidget extends StatelessWidget {
  final ui.Image _uiImage;
  final Path _clipPath;

  const MyWidget({
    Key? key,
    required ui.Image uiImage,
    required Path clipPath,
  })  : _uiImage = uiImage,
        _clipPath = clipPath,
        super(key: key);

  @override
  Widget build(BuildContext context) {
    final bounds = _clipPath.getBounds();
    
    final translateM = Float64List.fromList([
      1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      -bounds.left, -bounds.top, 0, 1
    ]);
    
    final localClipPath = _clipPath.transform(translateM);
    
    return ClipPath(
      clipper: _MyClipper(localClipPath),
      child: CustomPaint(
        painter: _MyPainter(_uiImage, bounds),
        child: SizedBox(
          width: bounds.width,
          height: bounds.height,
        ),
      ),
    );
  }
}

class _MyClipper extends CustomClipper<Path> {
  final Path _clipPath;

  _MyClipper(this._clipPath);

  @override
  Path getClip(Size size) => _clipPath;

  @override
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) => true;
}

class _MyPainter extends CustomPainter {
  final ui.Image _uiImage;
  final Rect _bounds;

  final _paint = Paint();

  _MyPainter(this._uiImage, this._bounds);

  @override
  void paint(Canvas canvas, Size size) {
    canvas.drawAtlas(
      _uiImage,
      [
        RSTransform.fromComponents(
          rotation: 0.0,
          scale: 1.0,
          // Center of the sprite relative to its rect
          anchorX: _bounds.width / 2,
          anchorY: _bounds.height / 2,
          // Location at which to draw the center of the sprite
          translateX: _bounds.width / 2,
          translateY: _bounds.height / 2,
        )
      ],
      [_bounds],
      null,
      null,
      null,
      _paint,
    );
  }

  @override
  bool shouldRepaint(_MyPainter oldDelegate) => false;
}

相关问题