[flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (6) 드래그로 Canvas 내 Object 이동시키기

Flutter Canvas 드래그로 Object 이동시키기

이 포스팅에서는 Flutter Canvas에서 드래그를 통해 객체(Object)를 이동시키는 방법을 설명합니다. 사용자는 특정 객체를 터치하고 드래그하여 원하는 위치로 이동시킬 수 있습니다.


1. Node 클래스

먼저, 이동 가능한 객체를 나타내는 Node 클래스를 정의합니다.


 

class Node {

  String id;

  String name;

  double x;

  double y;

 

  Node(this.id, this.name, this.x, this.y);

}

 

 

 

  • id: 객체의 고유 식별자.
  • name: 객체에 표시될 텍스트.
  • x, y: Canvas에서의 좌표.

2. DraggablePainter 클래스

Canvas에 배경, 그리드, 객체를 그리는 CustomPainter를 정의합니다.

class DraggablePainter extends CustomPainter {
  static const gridWidth = 50.0;
  static const gridHeight = 50.0;

  final double offsetX;
  final double offsetY;
  final List<Node> nodeList;

  DraggablePainter(this.nodeList, this.offsetX, this.offsetY);

  void _drawBackground(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.white70;
    canvas.drawRect(Rect.fromLTWH(0, 0, size.width, size.height), paint);
  }

  void _drawGrid(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.grey;
    for (double x = 0; x < size.width; x += gridWidth) {
      canvas.drawLine(Offset(x, 0), Offset(x, size.height), paint);
    }
    for (double y = 0; y < size.height; y += gridHeight) {
      canvas.drawLine(Offset(0, y), Offset(size.width, y), paint);
    }
  }

  void _drawNodes(Canvas canvas) {
    final paint = Paint()..color = Colors.amber;
    const textStyle = TextStyle(color: Colors.black, fontSize: 14);
    const radius = 30.0;

    for (final node in nodeList) {
      final center = Offset(node.x, node.y);
      canvas.drawCircle(center, radius, paint);
      _drawText(canvas, node.x, node.y, node.name, textStyle);
    }
  }

  void _drawText(Canvas canvas, double x, double y, String text, TextStyle style) {
    final textSpan = TextSpan(text: text, style: style);
    final textPainter = TextPainter(
      text: textSpan,
      textDirection: TextDirection.ltr,
    )..layout();
    final offset = Offset(x - textPainter.width / 2, y - textPainter.height / 2);
    textPainter.paint(canvas, offset);
  }

  @override
  void paint(Canvas canvas, Size size) {
    canvas.save();
    canvas.translate(offsetX, offsetY);

    _drawBackground(canvas, size);
    _drawGrid(canvas, size);
    _drawNodes(canvas);

    canvas.restore();
  }

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

 


3. GestureDetector를 활용한 드래그 이벤트 처리

사용자의 드래그 이벤트를 처리하여 객체를 이동시킵니다.

class DraggableObjectPageState extends State<DraggableObjectPage> {

  final List<Node> nodeList = [

    Node("1", "Node\n1", 150.0, 180.0),

    Node("2", "Node\n2", 220.0, 40.0),

    Node("3", "Node\n3", 380.0, 240.0),

    Node("4", "Node\n4", 640.0, 190.0),

    Node("5", "Node\n5", 480.0, 350.0),

  ];

 

  double offsetX = 0.0;

  double offsetY = 0.0;

  double preX = 0.0;

  double preY = 0.0;

  Node? currentNode;

 

  Node? _getNodeAt(double x, double y) {

    const radius = 30.0;

    for (final node in nodeList) {

      final distance = (node.x - x).abs() + (node.y - y).abs();

      if (distance <= radius) {

        return node;

      }

    }

    return null;

  }

 

  void _handlePanDown(DragDownDetails details) {

    final x = details.localPosition.dx - offsetX;

    final y = details.localPosition.dy - offsetY;

 

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

    currentNode = _getNodeAt(x, y);

    preX = details.localPosition.dx;

    preY = details.localPosition.dy;

  }

 

  void _handlePanUpdate(DragUpdateDetails details) {

    final dx = details.localPosition.dx - preX;

    final dy = details.localPosition.dy - preY;

 

    if (currentNode != null) {

      setState(() {

        currentNode!.x += dx;

        currentNode!.y += dy;

      });

    } else {

      setState(() {

        offsetX += dx;

        offsetY += dy;

      });

    }

 

    preX = details.localPosition.dx;

    preY = details.localPosition.dy;

  }

 

  @override

  Widget build(BuildContext context) {

    return Scaffold(

      body: GestureDetector(

        onPanDown: _handlePanDown,

        onPanUpdate: _handlePanUpdate,

        child: CustomPaint(

          painter: DraggablePainter(nodeList, offsetX, offsetY),

          child: Container(),

        ),

      ),

    );

  }

}

 

 

결론

이 코드를 통해 사용자는 Canvas 내부의 특정 객체를 드래그로 이동시킬 수 있습니다. GestureDetectorCustomPainter를 적절히 활용하여 직관적인 인터페이스를 제공합니다. 추가적으로, 객체와 Canvas 전체의 동시 이동도 처리할 수 있습니다.

 

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
27 [flutter (플루터 앱 개발)] Dart와 Flutter를 ChatGPT에게 배우다. file 졸리운_곰 2025.02.03 297
26 [flutter (플루터 앱 개발)] Flutter PDF 뷰어를 만드는 방법 : How to build a Flutter PDF viewer file 졸리운_곰 2025.01.19 215
» [flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (6) 드래그로 Canvas 내 Object 이동시키기 졸리운_곰 2025.01.19 277
24 [flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (5) 드래그로 Canvas 이동시키기 file 졸리운_곰 2025.01.18 157
23 [flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (4) Canvas에 Text 그리기 file 졸리운_곰 2025.01.18 201
22 [flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (3) Canvas내의 터치(마우스) 좌표 획득하는 방법 졸리운_곰 2025.01.17 247
21 [flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (2) Grid 격자 그리기 file 졸리운_곰 2025.01.17 503
20 [flutter (플루터 앱 개발)] Flutter Canvas 그리기 예제 - (1) 배경 색상 그리기 file 졸리운_곰 2025.01.16 241
19 [dart / flutter] Drawing Pixels With Dart : Dart 2d 그래픽 픽셀처리 file 졸리운_곰 2024.12.29 341
18 [flutter (플루터 앱 개발)] How to Implement Any UI in Flutter : 플러터에서 모든 UI를 구현하는 방법 file 졸리운_곰 2024.12.20 178
17 [flutter (플루터 앱 개발)] How to Implement Any UI in Flutter : 플러터에서 모든 UI를 구현하는 방법 file 졸리운_곰 2024.11.28 192
16 [flutter] A PocketBase backend for Flutter and Dart : Flutter 및 Dart용 PocketBase 백엔드 file 졸리운_곰 2024.10.29 266
15 [flutter] 44... 실 기기 테스트용 apk 파일 빌드하기 졸리운_곰 2024.10.26 233
14 [flutter (플루터 앱 개발)] [플러터] ios : error while build iOS app in Xcode : Sandbox: rsync.samba (13105) deny(1) file-write-create, Flutter failed to write to a file file 졸리운_곰 2024.07.26 296
13 [flutter (플루터 앱 개발)] [플러터] ios 앱 출시하기 file 졸리운_곰 2024.07.24 343
12 [flutter (플루터 앱 개발)] flutter 안드로이드 출시하기 keystore 적용 (keystore 분실 해결방법) 졸리운_곰 2024.07.16 333
11 [flutter (플루터 앱 개발)] Flutter - GetX를 이용한 상태관리 file 졸리운_곰 2024.07.12 326
10 [flutter (플루터 앱 개발)] flutter pocketbase 사용법 3탄(로그인) file 졸리운_곰 2024.06.10 413
9 [flutter (플루터 앱 개발)] flutter pocketbase 사용법 2탄(회원가입) file 졸리운_곰 2024.06.10 272
8 [flutter (플루터 앱 개발)] flutter pocketbase 사용방법 1탄(초기설정) file 졸리운_곰 2024.06.10 242
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED