This commit is contained in:
otsmr 2025-03-22 15:59:30 +01:00
parent 7e4787f0da
commit 3be963c8f9

View file

@ -1,4 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:twonly/src/components/image_editor/action_button.dart';
import 'package:twonly/src/components/image_editor/data/layer.dart'; import 'package:twonly/src/components/image_editor/data/layer.dart';
/// Emoji layer /// Emoji layer
@ -21,8 +23,10 @@ class _EmojiLayerState extends State<EmojiLayer> {
Offset initialOffset = Offset.zero; Offset initialOffset = Offset.zero;
Offset initialFocalPoint = Offset.zero; Offset initialFocalPoint = Offset.zero;
double initialScale = 1.0; double initialScale = 1.0;
bool deleteLayer = false;
bool twoPointerWhereDown = false; bool twoPointerWhereDown = false;
final GlobalKey _key = GlobalKey(); final GlobalKey outlineKey = GlobalKey();
final GlobalKey emojiKey = GlobalKey();
int pointers = 0; int pointers = 0;
@override @override
@ -43,76 +47,112 @@ class _EmojiLayerState extends State<EmojiLayer> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Positioned( if (widget.layerData.isDeleted) return Container();
left: widget.layerData.offset.dx, return Stack(
top: widget.layerData.offset.dy, key: outlineKey,
child: Listener( children: [
onPointerUp: (details) { Positioned(
setState(() { left: widget.layerData.offset.dx,
pointers--; top: widget.layerData.offset.dy,
if (pointers == 0) { child: Listener(
twoPointerWhereDown = false; onPointerUp: (details) {
} setState(() {
}); pointers--;
}, if (pointers == 0) {
onPointerDown: (details) { twoPointerWhereDown = false;
setState(() { }
pointers++; if (deleteLayer) {
}); widget.layerData.isDeleted = true;
}, }
child: GestureDetector( });
onScaleStart: (details) { },
// Store the initial scale and rotation onPointerDown: (details) {
initialScale = widget.layerData.size; // Reset initial scale setState(() {
initialRotation = widget.layerData.rotation; pointers++;
initialOffset = widget.layerData.offset; });
initialFocalPoint = },
Offset(details.focalPoint.dx, details.focalPoint.dy); child: GestureDetector(
onScaleStart: (details) {
initialScale = widget.layerData.size;
initialRotation = widget.layerData.rotation;
initialOffset = widget.layerData.offset;
initialFocalPoint =
Offset(details.focalPoint.dx, details.focalPoint.dy);
setState(() {}); setState(() {});
}, },
onScaleUpdate: (details) { onScaleUpdate: (details) {
if (twoPointerWhereDown == true && details.pointerCount != 2) { if (twoPointerWhereDown == true && details.pointerCount != 2) {
return; return;
} }
setState(() { final RenderBox outlineBox =
// Update the size based on the scale factor outlineKey.currentContext!.findRenderObject() as RenderBox;
twoPointerWhereDown = details.pointerCount >= 2; final RenderBox emojiBox =
emojiKey.currentContext!.findRenderObject() as RenderBox;
widget.layerData.size = initialScale * details.scale; bool isAtTheBottom =
(widget.layerData.offset.dy + emojiBox.size.height / 2) >
outlineBox.size.height - 80;
bool isInTheCenter = MediaQuery.of(context).size.width / 2 -
30 <
(widget.layerData.offset.dx +
emojiBox.size.width / 2) &&
MediaQuery.of(context).size.width / 2 + 20 >
(widget.layerData.offset.dx + emojiBox.size.width / 2);
// Update the rotation based on the rotation angle if (isAtTheBottom && isInTheCenter) {
widget.layerData.rotation = initialRotation + details.rotation; deleteLayer = true;
} else {
deleteLayer = false;
}
setState(() {
twoPointerWhereDown = details.pointerCount >= 2;
widget.layerData.size = initialScale * details.scale;
widget.layerData.rotation =
initialRotation + details.rotation;
// Update the position based on the translation // Update the position based on the translation
var dx = (initialOffset.dx) + var dx = (initialOffset.dx) +
(details.focalPoint.dx - initialFocalPoint.dx); (details.focalPoint.dx - initialFocalPoint.dx);
var dy = (initialOffset.dy) + var dy = (initialOffset.dy) +
(details.focalPoint.dy - initialFocalPoint.dy); (details.focalPoint.dy - initialFocalPoint.dy);
// var dy = details.focalPoint.dy - (renderBox.size.height / 2 + 34); widget.layerData.offset = Offset(dx, dy);
widget.layerData.offset = Offset(dx, dy); });
}); },
}, child: Transform.rotate(
onScaleEnd: (details) { angle: widget.layerData.rotation,
// Optionally, you can handle the end of the scale gesture here key: emojiKey,
}, child: Container(
child: Transform.rotate( padding: const EdgeInsets.all(44),
key: _key, color: Colors.transparent,
angle: widget.layerData.rotation, child: Text(
child: Container( widget.layerData.text.toString(),
padding: const EdgeInsets.all(44), style: TextStyle(
color: Colors.transparent, fontSize: widget.layerData.size,
child: Text( ),
widget.layerData.text.toString(), ),
style: TextStyle(
fontSize: widget.layerData.size,
), ),
), ),
), ),
), ),
), ),
), if (pointers > 0)
Positioned(
left: 0,
right: 0,
bottom: 20,
child: Center(
child: GestureDetector(
child: ActionButton(
FontAwesomeIcons.trashCan,
tooltipText: "",
color: deleteLayer ? Colors.red : Colors.white,
),
),
),
),
],
); );
} }
} }