Reactive Mind Map / 반응형 마인드맵
A highly customizable and interactive mind map package for Flutter with multiple layouts, dynamic sizing, and rich styling options.
Flutter용 다중 레이아웃, 동적 크기 조절, 다양한 스타일링 옵션을 제공하는 고도로 커스터마이징 가능한 인터랙티브 마인드맵 패키지입니다.
Screenshots / 스크린샷
Multiple layouts and customization options / 다양한 레이아웃과 커스터마이징 옵션
Demo / 데모
Interactive expand/collapse and smooth animations / 인터랙티브 확장/축소 및 부드러운 애니메이션
Features / 특징
🎨 완전한 커스터마이징 / Complete Customization
- 노드 모양 선택 (둥근 사각형, 원형, 다이아몬드, 육각형 등) / Node shapes (rounded rectangle, circle, diamond, hexagon, etc.)
- 색상, 텍스트 스타일, 그림자 효과 커스터마이징 / Colors, text styles, shadow effects customization
- 동적 노드 크기 조절 / Dynamic node sizing
- 연결선 스타일과 애니메이션 설정 / Connection line styles and animation settings
🎯 다양한 레이아웃 / Multiple Layouts
- 오른쪽/왼쪽/위/아래 방향 레이아웃 / Right/Left/Top/Bottom direction layouts
- 원형(Radial) 레이아웃 / Radial layout
- 좌우/상하 분할 레이아웃 / Horizontal/Vertical split layouts
⚡ 부드러운 애니메이션 / Smooth Animations
- 노드 확장/축소 애니메이션 / Node expand/collapse animations
- 커스터마이징 가능한 애니메이션 곡선과 지속시간 / Customizable animation curves and duration
- 하드웨어 가속 트랜지션 / Hardware-accelerated transitions
🖱️ 풍부한 인터랙션 / Rich Interactions
- 탭, 길게 누르기, 더블 탭 이벤트 / Tap, long press, double tap events
- 확대/축소, 팬 기능 / Pan & zoom functionality
- 노드 확장/축소 상태 추적 / Node expand/collapse state tracking
🎯 스마트 카메라 포커스 / Smart Camera Focus 🆕
- 자동 전체보기로 작은 위젯에서도 최적 표시 / Auto-fit for optimal display in small widgets
- 특정 노드 강조 및 가이드 투어 지원 / Specific node highlighting and guided tours
- 부드러운 포커스 이동 애니메이션 / Smooth focus transition animations
- 5가지 포커스 모드 (루트, 중앙, 전체, 리프, 커스텀) / 5 focus modes (root, center, fitAll, leaf, custom)
Event Handling / 이벤트 처리
MindMapWidget(
data: myData,
onNodeTap: (node) => print('Node tapped: ${node.title}'),
onNodeLongPress: (node) => _showNodeOptions(node),
onNodeExpandChanged: (node, isExpanded) =>
print('${node.title} ${isExpanded ? 'expanded' : 'collapsed'}'),
);
Installation / 설치
Add this to your package's pubspec.yaml
file:
pubspec.yaml
파일에 다음을 추가하세요:
dependencies:
reactive_mind_map: ^1.0.3
Then run / 그다음 실행하세요:
flutter pub get
Quick Start / 빠른 시작
import 'package:flutter/material.dart';
import 'package:reactive_mind_map/reactive_mind_map.dart';
class MyMindMap extends StatelessWidget {
@override
Widget build(BuildContext context) {
final mindMapData = MindMapData(
id: 'root',
title: 'My Project',
children: [
MindMapData(id: '1', title: 'Planning'),
MindMapData(id: '2', title: 'Development'),
MindMapData(id: '3', title: 'Testing'),
],
);
return Scaffold(
body: MindMapWidget(
data: mindMapData,
style: MindMapStyle(
layout: MindMapLayout.right,
nodeShape: NodeShape.roundedRectangle,
),
cameraFocus: CameraFocus.fitAll,
focusAnimation: Duration(milliseconds: 500),
onNodeTap: (node) => print('Tapped: ${node.title}'),
),
);
}
}
중요 사용법 주의사항 / Important Usage Notes
⚠️ 화면 크기 최적화 / Screen Size Optimization
MindMapWidget
은 기본적으로 화면 크기에 맞게 자동 조정됩니다Expanded
위젯 안에서 사용할 때는 추가 설정이 필요하지 않습니다- 팬/줌 기능이 기본으로 활성화되어 있어 큰 마인드맵도 쉽게 탐색할 수 있습니다
// ✅ 올바른 사용법 - 화면에 맞게 자동 조정
Widget build(BuildContext context) {
return Scaffold(
body: MindMapWidget(
data: root.value,
style: MindMapStyle(
layout: MindMapLayout.right,
nodeShape: NodeShape.roundedRectangle,
),
onNodeTap: (node) => print('Tapped: ${node.title}'),
),
);
}
// ✅ Expanded 안에서 사용하는 경우
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
SomeHeaderWidget(),
Expanded(
child: MindMapWidget(
data: root.value,
style: MindMapStyle(
layout: MindMapLayout.right,
nodeShape: NodeShape.roundedRectangle,
),
onNodeTap: (node) => print('Tapped: ${node.title}'),
),
),
],
),
);
}
Advanced Usage / 고급 사용법
Custom Node Builders / 커스텀 노드 빌더 🆕
You can create custom node designs using the nodeBuilder
property in MindMapStyle
:
MindMapStyle
의 nodeBuilder
속성을 사용하여 커스텀 노드 디자인을 만들 수 있습니다:
1. Style-Level Custom Node Builder / 스타일 레벨 커스텀 노드 빌더
Use the nodeBuilder
property in MindMapStyle
:
MindMapStyle
의 nodeBuilder
속성을 사용합니다:
MindMapWidget(
data: myData,
style: MindMapStyle(
layout: MindMapLayout.right,
nodeShape: NodeShape.roundedRectangle,
nodeBuilder: (node, isSelected, onTap, onLongPress, onDoubleTap) {
return GestureDetector(
onTap: onTap,
onLongPress: onLongPress,
onDoubleTap: onDoubleTap,
child: Container(
decoration: BoxDecoration(
color: node.color,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: isSelected ? Colors.yellow : Colors.transparent,
width: 2,
),
),
padding: EdgeInsets.all(12),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
node.title,
style: TextStyle(
color: node.textColor ?? Colors.white,
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
if (node.description != null) ...[
SizedBox(height: 4),
Text(
node.description!,
style: TextStyle(
color: node.textColor?.withOpacity(0.8) ?? Colors.white70,
fontSize: 12,
),
textAlign: TextAlign.center,
),
],
],
),
),
);
},
),
onNodeTap: (node) => print('Tapped: ${node.title}'),
)
Camera Focus Control / 카메라 포커스 제어
MindMapWidget(
data: myData,
cameraFocus: CameraFocus.fitAll,
focusNodeId: 'specific_node_id',
focusAnimation: Duration(milliseconds: 500),
focusMargin: EdgeInsets.all(20),
)
Camera Focus Options / 카메라 포커스 옵션
Focus Type / 포커스 타입 | When to Use / 사용 시기 |
---|---|
CameraFocus.rootNode |
Default view / 기본 뷰 |
CameraFocus.center |
Centered layouts / 중앙 정렬 레이아웃 |
CameraFocus.fitAll |
Small widgets, overview / 작은 위젯, 전체보기 |
CameraFocus.firstLeaf |
End-point focus / 끝점 포커스 |
CameraFocus.custom |
Specific node targeting / 특정 노드 타겟팅 |
Practical Examples / 실제 사용 예시
1. Small Container Optimization / 작은 컨테이너 최적화
Container(
height: 200,
child: MindMapWidget(
data: myData,
cameraFocus: CameraFocus.fitAll,
focusMargin: EdgeInsets.all(10),
focusAnimation: Duration(milliseconds: 300),
),
)
2. Specific Node Highlighting / 특정 노드 강조
MindMapWidget(
data: myData,
cameraFocus: CameraFocus.custom,
focusNodeId: 'important_milestone',
focusAnimation: Duration(milliseconds: 800),
initialScale: 1.2,
)
3. Guided Mind Map Tour / 가이드 마인드맵 투어
class GuidedMindMapTour extends StatefulWidget {
@override
State<GuidedMindMapTour> createState() => _GuidedMindMapTourState();
}
class _GuidedMindMapTourState extends State<GuidedMindMapTour> {
int currentStep = 0;
final List<String> tourSteps = ['intro', 'planning', 'development', 'testing'];
Widget build(BuildContext context) {
return Column(
children: [
Row(
children: [
ElevatedButton(
onPressed: currentStep > 0 ? _previousStep : null,
child: Text('이전'),
),
Text('${currentStep + 1} / ${tourSteps.length}'),
ElevatedButton(
onPressed: currentStep < tourSteps.length - 1 ? _nextStep : null,
child: Text('다음'),
),
],
),
Expanded(
child: MindMapWidget(
data: myData,
cameraFocus: CameraFocus.custom,
focusNodeId: tourSteps[currentStep],
focusAnimation: Duration(milliseconds: 600),
focusMargin: EdgeInsets.all(50),
),
),
],
);
}
void _nextStep() => setState(() => currentStep++);
void _previousStep() => setState(() => currentStep--);
}
4. Dynamic Focus Based on Data / 데이터에 따른 동적 포커스
Widget buildMindMap(MindMapData data) {
final nodeCount = _countAllNodes(data);
return MindMapWidget(
data: data,
cameraFocus: nodeCount > 10 ? CameraFocus.fitAll : CameraFocus.rootNode,
focusAnimation: Duration(milliseconds: 400),
);
}
Node Expand Camera Behavior / 노드 확장 카메라 동작 🆕
Control how the camera behaves when users expand or collapse nodes: 사용자가 노드를 펼치거나 접을 때 카메라가 어떻게 동작할지 제어할 수 있습니다:
MindMapWidget(
data: myData,
nodeExpandCameraBehavior: NodeExpandCameraBehavior.focusClickedNode,
)
Node Expand Camera Options / 노드 확장 카메라 옵션
Behavior / 동작 | Description / 설명 |
---|---|
NodeExpandCameraBehavior.none |
No camera movement (default) / 카메라 이동 없음 (기본값) |
NodeExpandCameraBehavior.focusClickedNode |
Focus on the clicked node / 클릭한 노드로 포커스 |
NodeExpandCameraBehavior.fitExpandedChildren |
Fit newly expanded children to view / 새로 펼쳐진 자식 노드들이 보이도록 조정 |
NodeExpandCameraBehavior.fitExpandedSubtree |
Fit entire expanded subtree to view / 펼쳐진 전체 서브트리가 보이도록 조정 |
Practical Examples / 실제 사용 예시
1. Focus on Clicked Node / 클릭한 노드에 포커스
MindMapWidget(
data: myData,
nodeExpandCameraBehavior: NodeExpandCameraBehavior.focusClickedNode,
focusAnimation: Duration(milliseconds: 400),
)
2. Show All Expanded Children / 펼쳐진 모든 자식 노드 표시
MindMapWidget(
data: myData,
nodeExpandCameraBehavior: NodeExpandCameraBehavior.fitExpandedChildren,
focusAnimation: Duration(milliseconds: 500),
)
3. Show Entire Subtree / 전체 서브트리 표시
MindMapWidget(
data: myData,
nodeExpandCameraBehavior: NodeExpandCameraBehavior.fitExpandedSubtree,
focusMargin: EdgeInsets.all(30),
)
Custom Styling / 커스텀 스타일링
final customStyle = MindMapStyle(
layout: MindMapLayout.radial,
nodeShape: NodeShape.circle,
enableAutoSizing: true,
connectionColor: Colors.blue,
animationDuration: Duration(milliseconds: 600),
defaultNodeColors: [Colors.blue, Colors.green, Colors.orange],
);
Event Handling / 이벤트 처리
MindMapWidget(
data: myData,
onNodeTap: (node) => print('Node tapped: ${node.title}'),
onNodeLongPress: (node) => _showNodeOptions(node),
onNodeExpandChanged: (node, isExpanded) =>
print('${node.title} ${isExpanded ? 'expanded' : 'collapsed'}'),
);
Available Options / 사용 가능한 옵션
Layouts / 레이아웃
Layout / 레이아웃 | Description / 설명 |
---|---|
MindMapLayout.right |
Traditional right-expanding / 오른쪽 확장 |
MindMapLayout.left |
Left-expanding / 왼쪽 확장 |
MindMapLayout.top |
Upward-expanding / 위쪽 확장 |
MindMapLayout.bottom |
Downward-expanding / 아래쪽 확장 |
MindMapLayout.radial |
Circular arrangement / 원형 배치 |
MindMapLayout.horizontal |
Left-right split / 좌우 분할 |
MindMapLayout.vertical |
Top-bottom split / 상하 분할 |
Node Shapes / 노드 모양
Shape / 모양 | Description / 설명 |
---|---|
NodeShape.roundedRectangle |
Rounded corners (default) / 둥근 모서리 (기본) |
NodeShape.circle |
Perfect circle / 완전한 원 |
NodeShape.rectangle |
Sharp corners / 날카로운 모서리 |
NodeShape.diamond |
Diamond shape / 다이아몬드 모양 |
NodeShape.hexagon |
Six-sided polygon / 육각형 |
NodeShape.ellipse |
Oval shape / 타원형 |
Performance / 성능
- 최적화된 렌더링 / Optimized rendering with custom painters
- 동적 간격 계산 / Smart spacing based on content
- 메모리 효율적 / Minimal widget tree overhead
- 부드러운 애니메이션 / Hardware-accelerated animations
License / 라이선스
This project is licensed under the MIT License - see the LICENSE file for details.
이 프로젝트는 MIT 라이선스 하에 있습니다 - 자세한 내용은 LICENSE 파일을 참조하세요.
Contributing / 기여
We welcome contributions! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated.
기여를 환영합니다! 버그 수정, 기능 추가, 문서 개선 등 모든 도움을 감사히 받겠습니다.
Quick Contributing Guide / 빠른 기여 가이드
-
🐛 Found a bug? / 버그를 발견하셨나요?
- Check existing issues first / 기존 이슈들을 먼저 확인하세요
- Use our Bug Report template / 버그 리포트 템플릿을 사용하세요
-
💡 Have a feature idea? / 기능 아이디어가 있으신가요?
- Use our Feature Request template / 기능 요청 템플릿을 사용하세요
-
❓ Need help? / 도움이 필요하신가요?
- Use our Question template / 질문 템플릿을 사용하세요
-
🔧 Want to contribute code? / 코드 기여를 원하시나요?
- Read our detailed Contributing Guide / 상세한 기여 가이드를 읽어보세요
- Fork the repo, make changes, and submit a PR / 저장소를 포크하고 변경사항을 만든 후 PR을 제출하세요
Development Setup / 개발 환경 설정
git clone https://github.com/YOUR_USERNAME/reactive_mind_map.git
cd reactive_mind_map
flutter pub get
flutter run
For detailed development guidelines, coding standards, and contribution process, please see our Contributing Guide.
자세한 개발 가이드라인, 코딩 표준, 기여 과정은 기여 가이드를 참조하세요.
Issues / 이슈
If you encounter any issues or have feature requests, please file them in the GitHub Issues section.
이슈가 발생하거나 기능 요청이 있으시면 GitHub Issues 섹션에 등록해 주세요.
변경 이력
최신 변경사항은 CHANGELOG.md를 확인하세요.