You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Custom Painter绘制的多边形内显示适配尺寸的图片

在CustomPainter的多边形内部绘制适配图片的解决方案

核心思路是利用Canvas的clipPath方法,先将画布裁剪为目标多边形的形状,再在裁剪区域内绘制图片,这样图片就只会显示在多边形内部。同时需要计算多边形的边界矩形,以此缩放图片来适配尺寸。

修改后的CustomPainter实现

import 'dart:ui' as ui;
import 'package:flutter/material.dart';

class MyPainter extends CustomPainter {
  final Offset firstPoint;
  final Offset secondPoint;
  final Offset thirdPoint;
  final Offset fourthPoint;
  final ui.Image image;

  MyPainter(
    this.firstPoint,
    this.secondPoint,
    this.thirdPoint,
    this.fourthPoint,
    this.image,
  );

  @override
  void paint(Canvas canvas, Size size) {
    // 创建目标多边形路径
    final polygonPath = Path()
      ..addPolygon([
        firstPoint,
        secondPoint,
        thirdPoint,
        fourthPoint,
      ], true);

    // 获取多边形的边界矩形,用于计算图片缩放和位置
    final pathBounds = polygonPath.getBounds();

    // 将画布裁剪为多边形形状,后续绘制仅在该区域生效
    canvas.clipPath(polygonPath);

    // 计算图片缩放比例:根据需求选择填充或适配模式
    final scaleX = pathBounds.width / image.width;
    final scaleY = pathBounds.height / image.height;
    // 取较大值:图片填充整个多边形(可能裁剪边缘);取较小值:图片完整显示(可能留空白)
    final scale = scaleX > scaleY ? scaleX : scaleY;

    final scaledWidth = image.width * scale;
    final scaledHeight = image.height * scale;

    // 计算图片偏移,让图片在多边形内居中
    final offsetX = pathBounds.left + (pathBounds.width - scaledWidth) / 2;
    final offsetY = pathBounds.top + (pathBounds.height - scaledHeight) / 2;

    // 绘制适配后的图片
    canvas.drawImageRect(
      image,
      Rect.fromLTWH(0, 0, image.width.toDouble(), image.height.toDouble()),
      Rect.fromLTWH(offsetX, offsetY, scaledWidth, scaledHeight),
      Paint(),
    );
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    if (oldDelegate is MyPainter) {
      return firstPoint != oldDelegate.firstPoint ||
          secondPoint != oldDelegate.secondPoint ||
          thirdPoint != oldDelegate.thirdPoint ||
          fourthPoint != oldDelegate.fourthPoint ||
          image != oldDelegate.image;
    }
    return true;
  }
}

补充:加载UI.Image的方法

要将资源图片转换为ui.Image,可以用以下异步方法:

import 'package:flutter/services.dart';

Future<ui.Image> loadAssetImage(String assetPath) async {
  final ByteData data = await rootBundle.load(assetPath);
  final ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List());
  final ui.FrameInfo frameInfo = await codec.getNextFrame();
  return frameInfo.image;
}

内容的提问来源于stack exchange,提问作者Yonkee

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 02:32:30