Flutter:Rect.fromCenter 没有在我点击的地方绘制正方形
Flutter: Rect.fromCenter not drawing square where I click
我试图在点击屏幕时绘制一个正方形。我有绘图逻辑工作,我可以点击它,但由于某种原因,它有点随机地绘制正方形。理想情况下,我希望它从点击点开始绘制。我点击的地方应该是新广场的中心。这是我单击 iOS 模拟器时当前发生的情况。
我尝试使用 event.pointerEvent.localPosition.dx
和 ...dy
,其中 event
是 SpriteBoxEvent
类型。我正在使用它们创建一个 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
。这是我解决它的方法:
- 已从您的
MyHomePage
小部件中删除 SingleChildScrollView
。
- 更改了
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);
}
},
),
),
]);
})));
- 修复了
SpriteSquare
中高度和宽度的错误顺序。所以这是现在 SpriteSquare
中的 paint 函数体:
canvas.drawRect(
Rect.fromLTWH(left, top, size.height, size.width),
Paint()..color = color
);
- 已更改
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);
}
}
经过这些更改,它现在可以正常工作了。
我试图在点击屏幕时绘制一个正方形。我有绘图逻辑工作,我可以点击它,但由于某种原因,它有点随机地绘制正方形。理想情况下,我希望它从点击点开始绘制。我点击的地方应该是新广场的中心。这是我单击 iOS 模拟器时当前发生的情况。
我尝试使用 event.pointerEvent.localPosition.dx
和 ...dy
,其中 event
是 SpriteBoxEvent
类型。我正在使用它们创建一个 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
。这是我解决它的方法:
- 已从您的
MyHomePage
小部件中删除SingleChildScrollView
。 - 更改了
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);
}
},
),
),
]);
})));
- 修复了
SpriteSquare
中高度和宽度的错误顺序。所以这是现在SpriteSquare
中的 paint 函数体:
canvas.drawRect(
Rect.fromLTWH(left, top, size.height, size.width),
Paint()..color = color
);
- 已更改
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);
}
}
经过这些更改,它现在可以正常工作了。