Skip to content

Instantly share code, notes, and snippets.

@roipeker
Created June 4, 2021 19:54
Show Gist options
  • Save roipeker/169351b6591ffaba82c88e8c3f90f167 to your computer and use it in GitHub Desktop.
Save roipeker/169351b6591ffaba82c88e8c3f90f167 to your computer and use it in GitHub Desktop.
GraphX issue #19: simpler gesture transform (zoom, drag, rotate)
/// live demo: https://graphx-gesture-simple.surge.sh
import 'package:flutter/material.dart';
import 'package:graphx/graphx.dart';
import 'package:graphx_zoompan/simple_zoom.dart';
void main() {
runApp(AppSimpleZoom());
}
class AppSimpleZoom extends StatefulWidget {
const AppSimpleZoom({Key? key}) : super(key: key);
@override
_AppSimpleZoomState createState() => _AppSimpleZoomState();
}
class _AppSimpleZoomState extends State<AppSimpleZoom> {
final scene = SimpleZoomScene();
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Simple transform')),
body: GestureDetector(
onScaleStart: scene.onScaleStart,
onScaleUpdate: scene.onScaleUpdate,
// onScaleEnd: scene.onScaleEnd,
child: SceneBuilderWidget(
builder: () => SceneController(front: scene),
),
),
floatingActionButton: FloatingActionButton(
child: Text('reset'),
onPressed: scene.resetTransform,
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:graphx/graphx.dart';
class SimpleZoomScene extends GSprite {
late GSprite content;
late GShape box;
late GIcon pivotIcon;
GPoint dragPoint = GPoint();
GPoint grabPoint = GPoint();
double grabRotation = 0.0;
double grabScale = 1.0;
@override
void addedToStage() {
super.addedToStage();
stage!.maskBounds = true;
stage!.color = Colors.grey.shade700;
/// a reference icon to understand how the pivot is assign for the
/// effect.
pivotIcon = GIcon(Icons.add_circle_outline, Colors.black45, 20);
pivotIcon.alignPivot(Alignment.center);
content = GSprite();
content.graphics
.beginFill(Colors.grey.shade400)
.lineStyle(3, Colors.white)
.drawGRect(stage!.stageRect)
.endFill();
box = GShape();
box.graphics.beginFill(Colors.blue).drawCircle(0, 0, 30).endFill();
box.setPosition(100, 100);
addChild(content);
content.addChild(box);
content.addChild(pivotIcon);
stage!.onMouseScroll.add(_onMouseScroll);
}
void _onMouseScroll(MouseInputData event) {
dragPoint = event.stagePosition;
adjustContentTransform();
/// use mouse scroll wheel as incrementer for zoom.
var _scale = content.scale;
_scale += -event.scrollDelta.y * .001;
setZoom(_scale);
}
void onScaleStart(ScaleStartDetails details) {
/// If you need, you can detect 1 or more fingers here.
/// for move vs zoom.
if (details.pointerCount == 1) {}
dragPoint = GPoint.fromNative(details.localFocalPoint);
adjustContentTransform();
grabRotation = content.rotation;
grabScale = content.scale;
}
void adjustContentTransform() {
final pivotPoint = content.globalToLocal(dragPoint);
pivotIcon.x = content.pivotX = pivotPoint.x;
pivotIcon.y = content.pivotY = pivotPoint.y;
globalToLocal(dragPoint, grabPoint);
content.setPosition(grabPoint.x, grabPoint.y);
}
void onScaleUpdate(ScaleUpdateDetails details) {
final focalPoint = GPoint.fromNative(details.localFocalPoint);
final deltaX = focalPoint.x - dragPoint.x;
final deltaY = focalPoint.y - dragPoint.y;
content.setPosition(grabPoint.x + deltaX, grabPoint.y + deltaY);
/// use touch scale ratio for zoom.
final _scale = details.scale * grabScale;
setZoom(_scale);
content.rotation = details.rotation + grabRotation;
}
void setZoom(double zoom) {
content.scale = zoom.clamp(.5, 3.0);
}
void resetTransform() {
content.pivotX = content.pivotY = content.rotation = 0;
content.scale = 1;
content.setPosition(0, 0);
pivotIcon.setPosition(0, 0);
// content.transformationMatrix.identity();
// pivotIcon.transformationMatrix.identity();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment