image_marker_viewer 1.0.3
image_marker_viewer: ^1.0.3 copied to clipboard
A Flutter package for adding interactive markers on images with custom colors, titles, and notes. Supports web, mobile, and desktop platforms.
image_marker_viewer #
A Flutter package for adding interactive markers on images with custom colors, titles, and notes. Supports web, mobile, and desktop platforms.
Features #
- π Interactive Markers: Add markers by tapping on images
- π¨ Custom Colors: Choose from predefined colors or use RGB color picker
- π Title & Notes: Add titles and notes to each marker
- π±οΈ Easy Management: Tap to edit, long press to delete markers
- πΎ Export/Import: Export markers to JSON and import them back
- π± Cross-Platform: Works on web, iOS, Android, macOS, Linux, and Windows
- π― Responsive: Markers stay in their relative position when image is resized
- β‘ Optimized Performance: Each marker manages its own state, reducing unnecessary rebuilds
- ποΈ Modular Architecture: Clean, maintainable code following SOLID principles
- πΈ Photo Support: Attach up to 3 photos per marker (Base64 encoded)
Getting Started #
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
image_marker_viewer: ^1.0.2
get: ^4.7.2
Usage #
Basic Example
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_marker_viewer/image_marker_viewer.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return GetMaterialApp(
home: Scaffold(
body: ImageMarkerViewer(
image: NetworkImage('https://example.com/image.jpg'),
onMarkerAdded: (marker) {
print('Marker added: ${marker.markerTitle}');
},
onMarkerSelected: (marker) {
print('Marker selected: ${marker.markerTitle}');
},
),
),
);
}
}
With File Picker
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:file_picker/file_picker.dart';
import 'package:image_marker_viewer/image_marker_viewer.dart';
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
Uint8List? selectedImageBytes;
Future<void> pickImage() async {
final result = await FilePicker.platform.pickFiles(
type: FileType.image,
);
if (result != null && result.files.single.bytes != null) {
setState(() {
selectedImageBytes = result.files.single.bytes;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: selectedImageBytes == null
? Center(child: Text('No image selected'))
: ImageMarkerViewer(
image: MemoryImage(selectedImageBytes!),
onMarkerAdded: (marker) {
print('Marker added at (${marker.x}, ${marker.y})');
},
),
floatingActionButton: FloatingActionButton(
onPressed: pickImage,
child: Icon(Icons.add_photo_alternate),
),
);
}
}
Multiple Images with Separate Marker Lists
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:image_marker_viewer/image_marker_viewer.dart';
// Each image can have its own marker list using tags
ImageMarkerViewer(
image: MemoryImage(image1Bytes),
tag: 'image_1', // Unique tag for this image
)
ImageMarkerViewer(
image: MemoryImage(image2Bytes),
tag: 'image_2', // Different tag for different markers
)
// Or use external controller
final controller = ImageMarkerController();
ImageMarkerViewer(
image: MemoryImage(imageBytes),
controller: controller,
)
Export/Import Markers
import 'package:image_marker_viewer/image_marker_viewer.dart';
import 'package:get/get.dart';
// Get the controller (with tag if used)
final controller = Get.find<ImageMarkerController>(tag: 'image_1');
// Export markers to JSON
String json = controller.exportToJson();
print(json);
// Import markers from JSON
controller.importFromJson(json);
API Reference #
ImageMarkerViewer #
The main widget for displaying images with markers.
Properties
image(ImageProvider, required): The image to displayenableAddMarker(bool, default: true): Enable/disable adding new markersonMarkerAdded(Function(ImageMarker)?): Callback when a marker is addedonMarkerSelected(Function(ImageMarker)?): Callback when a marker is selectedtag(String?, optional): Unique tag for this image's controller. Each image with a different tag will have its own marker listcontroller(ImageMarkerController?, optional): External controller instance. If provided,tagis ignored
ImageMarkerController #
Controller for managing markers.
Methods
addMarker(ImageMarker marker): Add a new markerremoveMarker(int index): Remove a marker at the given indexupdateTitle(int index, String? title): Update marker titleupdateNote(int index, String? note): Update marker noteupdateColor(int index, Color color): Update marker colorupdatePosition(int index, double x, double y): Update marker position (x, y in 0.0-1.0 range)addPhoto(int index, String photoBase64): Add a photo to a marker (max 3 photos per marker)removePhoto(int index, int photoIndex): Remove a photo from a markerexportToJson(): Export all markers to JSON stringimportFromJson(String jsonData): Import markers from JSON string
ImageMarker #
Model for marker data.
Properties
x(double): X coordinate (0.0 to 1.0)y(double): Y coordinate (0.0 to 1.0)color(Color): Marker colormarkerTitle(String?): Optional marker titlenote(String?): Optional marker notephotos(List
Interaction #
- Tap on image: Add a new marker (if
enableAddMarkeris true) - Tap on marker: Edit the marker
- Long press on marker: Delete the marker (with confirmation)
- Drag marker: Move marker to a new position by dragging it
What's New in v1.0.2 #
Performance Improvements #
- Optimized State Management: Each marker widget now manages its own state independently using reactive programming. This means when one marker changes, only that specific marker rebuilds, not the entire UI.
- Reduced Rebuilds: Significant performance improvement when working with multiple markers.
Code Quality #
- SOLID Principles: Complete refactoring following SOLID design principles for better maintainability
- Modular Architecture: Code split into logical, reusable components
- Comprehensive Documentation: Added DartDoc comments throughout the codebase
- Enhanced Error Handling: Improved bounds checking and error handling
Bug Fixes #
- Fixed marker dragging/positioning issues for stable marker movement
- Improved marker position calculation accuracy
Example #
See the example directory for a complete example application.
License #
This project is licensed under the MIT License - see the LICENSE file for details.
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
Issues #
If you encounter any issues, please file an issue on the GitHub repository.