jsoncanvasviewer 0.1.0
jsoncanvasviewer: ^0.1.0 copied to clipboard
A Flutter package for creating, editing and rendering interactive JSON-based canvas layouts with drag-and-drop support and real-time visual editing.
import 'package:flutter/material.dart';
import 'package:jsoncanvasviewer/jsoncanvasviewer.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'JSON Canvas Viewer Example',
debugShowCheckedModeBanner: false,
theme: ThemeData(
brightness: Brightness.dark,
scaffoldBackgroundColor: EditorTheme.backgroundColor,
colorScheme: const ColorScheme.dark(
surface: EditorTheme.surfaceColor,
primary: EditorTheme.textColor,
onSurface: EditorTheme.textColor,
),
),
home: const ExampleHomePage(),
);
}
}
class ExampleHomePage extends StatefulWidget {
const ExampleHomePage({super.key});
@override
State<ExampleHomePage> createState() => _ExampleHomePageState();
}
class _ExampleHomePageState extends State<ExampleHomePage> {
int _selectedIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('JSON Canvas Viewer Examples'),
backgroundColor: EditorTheme.surfaceColor,
),
body: IndexedStack(
index: _selectedIndex,
children: const [
FullEditorExample(),
SimpleCanvasExample(),
InteractiveExample(),
],
),
bottomNavigationBar: NavigationBar(
selectedIndex: _selectedIndex,
onDestinationSelected: (index) {
setState(() {
_selectedIndex = index;
});
},
destinations: const [
NavigationDestination(
icon: Icon(Icons.edit),
label: 'Full Editor',
),
NavigationDestination(
icon: Icon(Icons.dashboard),
label: 'Simple Canvas',
),
NavigationDestination(
icon: Icon(Icons.touch_app),
label: 'Interactive',
),
],
),
);
}
}
/// Example 1: Full editor with JSON editing and canvas viewing
class FullEditorExample extends StatelessWidget {
const FullEditorExample({super.key});
@override
Widget build(BuildContext context) {
return const HomePage();
}
}
/// Example 2: Simple canvas viewer without editor
class SimpleCanvasExample extends StatelessWidget {
const SimpleCanvasExample({super.key});
static const String sampleJson = '''
{
"canvas": {
"width": 360,
"height": 640,
"backgroundColor": "#F8F9FA"
},
"elements": [
{
"type": "gradient",
"gradientType": "linear",
"fullSize": true,
"startX": 0.0,
"startY": 0.0,
"endX": 1.0,
"endY": 1.0,
"colorStops": [
{"color": "#667EEA", "stop": 0.0, "opacity": 1.0},
{"color": "#764BA2", "stop": 1.0, "opacity": 1.0}
],
"zIndex": 0
},
{
"type": "rect",
"x": "center",
"y": 150,
"width": 300,
"height": 350,
"color": "#FFFFFF",
"borderRadius": 20,
"opacity": 0.95,
"zIndex": 1
},
{
"type": "circle",
"x": "center",
"y": 130,
"width": 80,
"height": 80,
"color": "#667EEA",
"zIndex": 2
},
{
"type": "icon",
"name": "star",
"x": "center",
"y": 155,
"size": 40,
"color": "#FFFFFF",
"zIndex": 3
},
{
"type": "text",
"content": "Welcome!",
"x": "center",
"y": 230,
"fontSize": 32,
"fontFamily": "Pacifico",
"weight": "regular",
"color": "#2D3748",
"textAlign": "center",
"zIndex": 2
},
{
"type": "text",
"content": "This is a simple example of JSON Canvas Viewer",
"x": "center",
"y": 280,
"fontSize": 14,
"fontFamily": "Roboto",
"color": "#718096",
"textAlign": "center",
"maxWidth": 260,
"lineHeight": 1.5,
"zIndex": 2
},
{
"type": "rect",
"x": "center",
"y": 380,
"width": 200,
"height": 50,
"color": "#667EEA",
"borderRadius": 25,
"zIndex": 2
},
{
"type": "text",
"content": "Get Started",
"x": "center",
"y": 395,
"fontSize": 16,
"fontFamily": "Roboto",
"weight": "bold",
"color": "#FFFFFF",
"textAlign": "center",
"zIndex": 3
}
]
}
''';
@override
Widget build(BuildContext context) {
return Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 20),
const Text(
'Simple Canvas Example',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 20),
const JsonCanvasViewer(
jsonString: sampleJson,
),
const SizedBox(height: 20),
],
),
),
);
}
}
/// Example 3: Interactive canvas with element manipulation
class InteractiveExample extends StatefulWidget {
const InteractiveExample({super.key});
@override
State<InteractiveExample> createState() => _InteractiveExampleState();
}
class _InteractiveExampleState extends State<InteractiveExample> {
String _lastAction = 'Drag or resize elements to see updates';
static const String interactiveJson = '''
{
"canvas": {
"width": 360,
"height": 640,
"backgroundColor": "#FFFFFF"
},
"elements": [
{
"type": "rect",
"x": 50,
"y": 100,
"width": 100,
"height": 100,
"color": "#FF6B6B",
"borderRadius": 10,
"zIndex": 1
},
{
"type": "rect",
"x": 200,
"y": 100,
"width": 100,
"height": 100,
"color": "#4ECDC4",
"borderRadius": 10,
"zIndex": 1
},
{
"type": "circle",
"x": 125,
"y": 250,
"width": 80,
"height": 80,
"color": "#FFE66D",
"zIndex": 1
},
{
"type": "text",
"content": "Drag me!",
"x": "center",
"y": 370,
"fontSize": 24,
"fontFamily": "Roboto",
"weight": "bold",
"color": "#2D3748",
"textAlign": "center",
"zIndex": 2
}
]
}
''';
void _handleElementMoved(
int elementIndex,
double newX,
double newY, {
double? newWidth,
double? newHeight,
}) {
setState(() {
if (newWidth != null && newHeight != null) {
_lastAction =
'Element $elementIndex resized to ${newWidth.toInt()}x${newHeight.toInt()} at (${newX.toInt()}, ${newY.toInt()})';
} else {
_lastAction =
'Element $elementIndex moved to (${newX.toInt()}, ${newY.toInt()})';
}
});
}
@override
Widget build(BuildContext context) {
return Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 20),
const Text(
'Interactive Canvas Example',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 10),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 20),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: EditorTheme.surfaceColor,
borderRadius: BorderRadius.circular(8),
),
child: Text(
_lastAction,
style: const TextStyle(fontSize: 14),
textAlign: TextAlign.center,
),
),
),
const SizedBox(height: 20),
JsonCanvasViewer(
jsonString: interactiveJson,
onElementMoved: _handleElementMoved,
),
const SizedBox(height: 20),
const Padding(
padding: EdgeInsets.symmetric(horizontal: 20),
child: Text(
'Try dragging the elements or resizing them using the corner handles!',
style: TextStyle(fontSize: 12, fontStyle: FontStyle.italic),
textAlign: TextAlign.center,
),
),
const SizedBox(height: 20),
],
),
),
);
}
}