Flutter:Rect.fromCenter 没有在我点击的地方绘制正方形

Flutter: Rect.fromCenter not drawing square where I click

我试图在点击屏幕时绘制一个正方形。我有绘图逻辑工作,我可以点击它,但由于某种原因,它有点随机地绘制正方形。理想情况下,我希望它从点击点开始绘制。我点击的地方应该是新广场的中心。这是我单击 iOS 模拟器时当前发生的情况。

我尝试使用 event.pointerEvent.localPosition.dx...dy,其中 eventSpriteBoxEvent 类型。我正在使用它们创建一个 Offset 实例,它将在 Rect.fromCenter 中使用,因为我认为最好与我的指针坐标一起使用,因为我希望它们成为正方形的中心。

下面是我的 SpriteSquare 小部件和父小部件中的 handleAdd 函数的代码,MySpriteGame(减去导入,因为它们不会引起任何问题) .

Here 是完整的 GitHub 存储库。

sprite_square.dart

class SpriteSquare extends NodeWithSize {
  
  Color color;
  Function handler;
  double left;
  double top;

  SpriteSquare(size, this.color, this.handler, this.top, this.left) : super(size){
    userInteractionEnabled = true;
  }

  @override handleEvent(SpriteBoxEvent event) {
    handler(event);
    return true;
  }

  @override
    Future<void> paint(Canvas canvas) async {
      canvas.drawRect(
        Rect.fromLTWH(left, top, size.height, size.width),
        Paint()..color = color
      );
    }
}

handleAdd

handleAdd(SpriteBoxEvent event) {
    final _whitesquare = SpriteSquare(
      const Size(50.0, 50.0), 
      const Color(0xFFFFFFFF), 
      handleRemoveSelf, 
      Offset(event.pointerEvent.localPosition.dx, event.pointerEvent.localPosition.dy)
    );
    _background.addChild(_whitesquare);
    return true;
  }

您正在创建尺寸错误的背景 SpriteSquare,然后您添加了其他 SpriteSquare,其位置是根据触摸事件位置计算的,转换为 SpriteWidget 的本地位置,这可以比你的背景小或大 SpriteSquare。这是我解决它的方法:

  1. 已从您的 MyHomePage 小部件中删除 SingleChildScrollView
  2. 更改了 LayoutBuilder 在小部件树中的位置。所以最终MyHomePage的构建函数体是这样的:
return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: Center(child: LayoutBuilder(builder: (ctx, constrain
      return Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'Select Game Engine',
            ),
            DropdownButton<String>(
              value: _whichEngine,
              icon: const Icon(Icons.arrow_downward),
              iconSize: 24,
              elevation: 16,
              style: const TextStyle(color: Colors.deepPurple)
              underline: Container(
                height: 2,
                color: Colors.deepPurpleAccent,
              ),
              onChanged: (String? newValue) {
                setState(() {
                  _whichEngine = newValue!;
                });
              },
              items: <String>[
                'Flame',
                'Quill',
                'SpriteWidget',
                'Feathers',
                'Unity'
              ].map<DropdownMenuItem<String>>((String value) {
                return DropdownMenuItem<String>(
                  value: value,
                  child: Text(value),
                );
              }).toList(),
            ),
            Expanded(
              child: LayoutBuilder(
                builder: (context, constraints) {
                  final size =
                      Size(constraints.maxWidth, constraints.m
                  if (_whichEngine == 'Flame') {
                    return GameWidget(
                      game: MyFlameGame(),
                    );
                  } else if (_whichEngine == 'SpriteWidget') {
                    return MySpriteGame(size: size);
                  } else {
                    return MySpriteGame(size: size);
                  }
                },
              ),
            ),
          ]);
    })));
  1. 修复了 SpriteSquare 中高度和宽度的错误顺序。所以这是现在 SpriteSquare 中的 paint 函数体:
canvas.drawRect(
  Rect.fromLTWH(left, top, size.height, size.width),
  Paint()..color = color
);
  1. 已更改 MySpriteGame 以从其父级获取尺寸并使用该尺寸构建背景并调整 handleAdd 中的值:
class MySpriteGame extends StatelessWidget {
  final _background;

  MySpriteGame({Key? key, required Size size})
      : _background = SpriteSquare(size, const Color(0xFF000000), () {}, 0, 0),
        super(key: key) {}

  handleAdd(SpriteBoxEvent event) {
    final _whitesquare = SpriteSquare(
      const Size(50.0, 50.0),
      const Color(0xFFFFFFFF),
      handleRemoveSelf,
      event.pointerEvent.localPosition.dy - 25,
      event.pointerEvent.localPosition.dx - 25,
    );
    _background.addChild(_whitesquare);
    return true;
  }

  handleRemoveSelf(SpriteBoxEvent event) {
    print('hello');
    return true;
  }

  @override
  Widget build(BuildContext context) {
    _background.handler = handleAdd;
    return SpriteWidget(_background);
  }
}

经过这些更改,它现在可以正常工作了。