11import 'dart:async' ;
22import 'dart:convert' ;
33import 'dart:developer' ;
4- import 'dart:ui' ;
4+ import 'dart:typed_data' ;
5+ import 'dart:ui' as ui;
6+ import 'package:http/http.dart' as http;
7+ import 'package:flutter/services.dart' ;
58import 'package:beacon/core/resources/data_state.dart' ;
69import 'package:beacon/core/utils/constants.dart' ;
710import 'package:beacon/domain/entities/beacon/beacon_entity.dart' ;
@@ -13,15 +16,13 @@ import 'package:beacon/domain/usecase/hike_usecase.dart';
1316import 'package:beacon/locator.dart' ;
1417import 'package:beacon/presentation/hike/cubit/location_cubit/location_state.dart' ;
1518import 'package:beacon/presentation/hike/cubit/panel_cubit/panel_cubit.dart' ;
16- import 'package:beacon/presentation/widgets/custom_label_marker.dart' ;
1719import 'package:flutter/material.dart' ;
1820import 'package:flutter_animarker/core/ripple_marker.dart' ;
1921import 'package:flutter_bloc/flutter_bloc.dart' ;
2022import 'package:flutter_polyline_points/flutter_polyline_points.dart' ;
2123import 'package:gap/gap.dart' ;
2224import 'package:google_maps_flutter/google_maps_flutter.dart' ;
2325import 'package:location/location.dart' ;
24- import 'package:http/http.dart' as http;
2526import 'package:responsive_sizer/responsive_sizer.dart' ;
2627import 'package:vibration/vibration.dart' ;
2728
@@ -63,6 +64,29 @@ class LocationCubit extends Cubit<LocationState> {
6364 mapController = controller;
6465 }
6566
67+ void centerMap () {
68+ Location location = new Location ();
69+ location.changeSettings (
70+ interval: 5000 , accuracy: LocationAccuracy .high, distanceFilter: 0 );
71+
72+ _streamLocaitonData =
73+ location.onLocationChanged.listen ((LocationData newPosition) async {
74+ var latLng = locationDataToLatLng (newPosition);
75+
76+ mapController? .animateCamera (CameraUpdate .newCameraPosition (
77+ CameraPosition (target: latLng, zoom: 15 ),
78+ ));
79+ });
80+ }
81+
82+ void zoomIn () {
83+ mapController? .animateCamera (CameraUpdate .zoomIn ());
84+ }
85+
86+ void zoomOut () {
87+ mapController? .animateCamera (CameraUpdate .zoomOut ());
88+ }
89+
6690 Future <void > loadBeaconData (
6791 BeaconEntity beacon, TickerProvider vsync, BuildContext context) async {
6892 this .vsync = vsync;
@@ -675,7 +699,7 @@ class LocationCubit extends Cubit<LocationState> {
675699 _hikeMarkers.where ((element) => element.markerId == markerId);
676700
677701 if (existingMarkers.isEmpty) {
678- var newMarker = await createMarker (landMark);
702+ var newMarker = await createMarkerWithCircularNetworkImage (landMark);
679703 _hikeMarkers.add (newMarker);
680704 } else {
681705 // If the marker exists, update its position
@@ -717,25 +741,94 @@ class LocationCubit extends Cubit<LocationState> {
717741 }
718742 }
719743
720- Future <Marker > createMarker ( LandMarkEntity landmark) async {
721- final pictureRecorder = PictureRecorder ();
722- final canvas = Canvas (pictureRecorder);
723- final customMarker = CustomMarker (text : landmark.title ! );
724- customMarker. paint (canvas, Size ( 100 , 100 ));
725- final picture = pictureRecorder. endRecording ();
726- final image = await picture. toImage ( 100 , 100 );
727- final bytes = await image. toByteData (format : ImageByteFormat .png );
744+ Future <Marker > createMarkerWithCircularNetworkImage (
745+ LandMarkEntity landmark) async {
746+ final Uint8List markerIcon = await getCircularImageWithBorderAndPointer (
747+ "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuNhTZJTtkR6b-ADMhmzPvVwaLuLdz273wvQ&s" ,
748+ size : 80 ,
749+ borderColor : Colors .deepPurple,
750+ borderWidth : 4 ,
751+ );
728752
729753 return Marker (
730754 markerId: MarkerId (landmark.id! .toString ()),
731755 position: locationToLatLng (landmark.location! ),
732- icon: BitmapDescriptor .bytes (bytes ! .buffer. asUint8List () ),
756+ icon: BitmapDescriptor .fromBytes (markerIcon ),
733757 infoWindow: InfoWindow (
734758 title: 'Created by: ${landmark .createdBy ?.name ?? 'Anonymous' }' ,
735759 ),
736760 );
737761 }
738762
763+ Future <Uint8List > getCircularImageWithBorderAndPointer (
764+ String imageUrl, {
765+ int size = 150 ,
766+ Color borderColor = Colors .red,
767+ double borderWidth = 6 ,
768+ }) async {
769+ final http.Response response = await http.get (Uri .parse (imageUrl));
770+ final Uint8List bytes = response.bodyBytes;
771+
772+ final ui.Codec codec = await ui.instantiateImageCodec (
773+ bytes,
774+ targetWidth: size,
775+ targetHeight: size,
776+ );
777+ final ui.FrameInfo frame = await codec.getNextFrame ();
778+ final ui.Image image = frame.image;
779+
780+ final double radius = size / 2 ;
781+ final double triangleHeight = size * 0.35 ; // Increase triangle height here
782+ final double totalHeight = size + triangleHeight;
783+
784+ final ui.PictureRecorder recorder = ui.PictureRecorder ();
785+ final Canvas canvas = Canvas (recorder);
786+ final Paint paint = Paint ()..isAntiAlias = true ;
787+
788+ final Offset circleCenter = Offset (radius, radius);
789+
790+ // 1. Draw triangle FIRST (so it goes behind the circle)
791+ paint
792+ ..style = PaintingStyle .fill
793+ ..color = borderColor;
794+
795+ final Path trianglePath = Path ()
796+ ..moveTo (radius - 25 , size.toDouble () - 10 ) // narrower base
797+ ..lineTo (radius + 25 , size.toDouble () - 10 )
798+ ..lineTo (radius, size + triangleHeight - 10 )
799+ ..close ();
800+
801+ canvas.drawPath (trianglePath, paint);
802+
803+ // 2. Draw white background circle
804+ paint.color = Colors .white;
805+ canvas.drawCircle (circleCenter, radius, paint);
806+
807+ // 3. Clip and draw circular image
808+ Path clipPath = Path ()
809+ ..addOval (
810+ Rect .fromCircle (center: circleCenter, radius: radius - borderWidth));
811+ canvas.save ();
812+ canvas.clipPath (clipPath);
813+ canvas.drawImage (image, Offset .zero, Paint ());
814+ canvas.restore ();
815+
816+ // 4. Draw circular border
817+ paint
818+ ..color = borderColor
819+ ..style = PaintingStyle .stroke
820+ ..strokeWidth = borderWidth;
821+ canvas.drawCircle (circleCenter, radius - borderWidth / 2 , paint);
822+
823+ // 5. Convert to PNG bytes
824+ final ui.Image finalImage =
825+ await recorder.endRecording ().toImage (size, totalHeight.toInt ());
826+ final ByteData ? byteData =
827+ await finalImage.toByteData (format: ui.ImageByteFormat .png);
828+
829+ return byteData! .buffer.asUint8List ();
830+ }
831+
739832 void changeGeofenceRadius (double radius, LatLng center) {
740833 var index = _geofence
741834 .toList ()
0 commit comments