Welcome to ZaiZheLe Developer Zone-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
753 views
in Technique[技术] by (71.8m points)

flutter - How to set "z-index" of canvas elements?

So I got this painter to draw a minimap for my game:

class MiniMapPainter extends CustomPainter {
  final GameMap map;
  final double tileSize;
  final List<ui.Image> images;

  MiniMapPainter(
      {@required this.images, @required this.map, @required this.tileSize});

  @override
  void paint(Canvas canvas, Size size) {
    var row = 0;
    var column = 0;

    map.encodedMap.runes.forEach((charCode) {
      final character = String.fromCharCode(charCode);

      if (character == map.rowSeparator) {
        row++;
        column = 0;
      } else if (character == map.colSeparator) {
        column++;
      } else {
        final code = map.codeFromInt(int.parse(character));
        final paint = _paintFromMapCode(code);

        switch (code) {
          case MapCode.TreasureChestClosed:
          case MapCode.TreasureChestLocked:
            _paintImageFromAsset(canvas, column, row, images[0]);
            break;
          default:
            canvas.drawRect(
                Rect.fromLTWH(
                  _getLeft(column), // Determines position on x-axis
                  _getTop(row), // Determines position on y-axis
                  tileSize,
                  tileSize,
                ),
                paint);
            break;
        }
      }
    });
  }

  double _getTop(int index) {
    return index * tileSize;
  }

  double _getLeft(int index) {
    return (index % map.columns).floor().toDouble() * tileSize;
  }

  void _paintImageFromAsset(Canvas canvas, int x, int y, ui.Image asset) {
    final size = tileSize * 3;
    final offset = (size / 2);

    paintImage(
        canvas: canvas,
        rect: Rect.fromLTWH(
          _getLeft(x) - offset,
          _getTop(y) - offset,
          size,
          size,
        ),
        image: asset);
  }

  Paint _paintFromMapCode(MapCode code) {
    var paint = Paint();

    switch (code) {
      case MapCode.Obstacle:
        paint.color = Colors.black;
        break;
      case MapCode.DamageTrap:
        paint.color = Colors.red[300];
        break;
      case MapCode.StunTrap:
        paint.color = Colors.red[100];
        break;
      default:
        paint.color = Colors.grey[300];
        break;
    }

    return paint;
  }

  @override
  bool shouldRepaint(MiniMapPainter oldDelegate) => true;
  @override
  bool shouldRebuildSemantics(MiniMapPainter oldDelegate) => true;
}

Some things require an image instead of a rectangle, such as treasures. So I added the _paintImageFromAsset method which works great but there's a problem which can be seen in this screenshot:

minimap example

As you can see any rectangles drawn after the treasures seem to get a higher z-index so they clip the images.

I haven't found a way to set the z-index of custom canvas elements like this. I would like to avoid having to draw images after all the rectangles if possible.

How can I do this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Maybe use two widgets? e.g.

Stack(children: [
  CustomPaint(paint: ThePaintToCreateThingsWithSmallZIndex()),
  CustomPaint(paint: ThePaintToCreateThingsWithBigZIndex()),
])

By doing this, you do not need to care about the order of drawing, and even if ThePaintToCreateThingsWithSmallZIndex is painted later, it is still on below.

Do not forget to paint transparently instead of white background.

(The code is only for demo purpose and cannot be compiled, of course)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to ZaiZheLe Developer Zone-Open, Learning and Share
...