-
Notifications
You must be signed in to change notification settings - Fork 2
feat: Add image and icon props to Marker component #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -671,6 +671,7 @@ class GoogleMapProvider(private val context: Context) : | |||||||||||||||||||||
| isDraggable = markerView.draggable | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| val marker = markerView.marker ?: return | ||||||||||||||||||||||
| if (markerView.hasCustomView) { | ||||||||||||||||||||||
| if (markerView.scaleChanged) { | ||||||||||||||||||||||
| markerView.applyScaleToMarker() | ||||||||||||||||||||||
|
|
@@ -679,6 +680,8 @@ class GoogleMapProvider(private val context: Context) : | |||||||||||||||||||||
| if (!markerView.rasterize) { | ||||||||||||||||||||||
| positionLiveMarker(markerView) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } else if (markerView.hasIconUri || markerView.hasImageUri) { | ||||||||||||||||||||||
| applyImageIconToMarker(markerView, marker) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -712,9 +715,62 @@ class GoogleMapProvider(private val context: Context) : | |||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| showLiveMarker(markerView) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } else if (markerView.hasIconUri || markerView.hasImageUri) { | ||||||||||||||||||||||
| applyImageIconToMarker(markerView, marker) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private fun applyImageIconToMarker(markerView: LuggMarkerView, marker: AdvancedMarker) { | ||||||||||||||||||||||
| val isIcon = markerView.hasIconUri | ||||||||||||||||||||||
| val cached = if (isIcon) markerView.cachedIconBitmap else markerView.cachedImageBitmap | ||||||||||||||||||||||
| if (cached != null) { | ||||||||||||||||||||||
| val scaled = scaleBitmap(cached, markerView.scale) | ||||||||||||||||||||||
| marker.setIcon(BitmapDescriptorFactory.fromBitmap(scaled)) | ||||||||||||||||||||||
| return | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| val uri = if (isIcon) markerView.iconUri else markerView.imageUri | ||||||||||||||||||||||
| Thread { | ||||||||||||||||||||||
| try { | ||||||||||||||||||||||
| val bitmap = loadBitmapFromUri(uri) | ||||||||||||||||||||||
| if (bitmap != null) { | ||||||||||||||||||||||
| mapView?.post { | ||||||||||||||||||||||
| if (isIcon) { | ||||||||||||||||||||||
| markerView.cachedIconBitmap = bitmap | ||||||||||||||||||||||
| } else { | ||||||||||||||||||||||
| markerView.cachedImageBitmap = bitmap | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| val scaled = scaleBitmap(bitmap, markerView.scale) | ||||||||||||||||||||||
| marker.setIcon(BitmapDescriptorFactory.fromBitmap(scaled)) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } catch (_: Exception) {} | ||||||||||||||||||||||
| }.start() | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
Comment on lines
+723
to
+748
|
||||||||||||||||||||||
|
|
||||||||||||||||||||||
| private fun loadBitmapFromUri(uri: String): android.graphics.Bitmap? { | ||||||||||||||||||||||
| if (uri.startsWith("asset://")) { | ||||||||||||||||||||||
| val assetPath = uri.removePrefix("asset://") | ||||||||||||||||||||||
| return context.assets.open(assetPath).use { stream -> | ||||||||||||||||||||||
| android.graphics.BitmapFactory.decodeStream(stream) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| val connection = java.net.URL(uri).openConnection() as java.net.HttpURLConnection | ||||||||||||||||||||||
| connection.instanceFollowRedirects = true | ||||||||||||||||||||||
| connection.connect() | ||||||||||||||||||||||
| return try { | ||||||||||||||||||||||
| android.graphics.BitmapFactory.decodeStream(connection.inputStream) | ||||||||||||||||||||||
|
Comment on lines
+759
to
+761
|
||||||||||||||||||||||
| connection.connect() | |
| return try { | |
| android.graphics.BitmapFactory.decodeStream(connection.inputStream) | |
| connection.connectTimeout = 10_000 | |
| connection.readTimeout = 10_000 | |
| connection.connect() | |
| return try { | |
| connection.inputStream.use { stream -> | |
| android.graphics.BitmapFactory.decodeStream(stream) | |
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -776,6 +776,21 @@ - (MKAnnotationView *)mapView:(MKMapView *)mapView | |
| } | ||
|
|
||
| if (!markerView.hasCustomView) { | ||
| if (markerView.hasImageUri) { | ||
| MKAnnotationView *annotationView = | ||
| [[MKAnnotationView alloc] initWithAnnotation:annotation | ||
| reuseIdentifier:nil]; | ||
| annotationView.canShowCallout = YES; | ||
| annotationView.displayPriority = MKFeatureDisplayPriorityRequired; | ||
| annotationView.layer.zPosition = markerView.zIndex; | ||
| annotationView.zPriority = markerView.zIndex; | ||
| annotationView.draggable = markerView.draggable; | ||
| [self applyCalloutView:markerView annotationView:annotationView]; | ||
| [self addCenterTapGesture:annotationView]; | ||
| markerAnnotation.annotationView = annotationView; | ||
| [self applyImageMarkerStyle:markerView annotationView:annotationView]; | ||
| return annotationView; | ||
| } | ||
| LuggMarkerAnnotationView *markerAnnotationView = | ||
| [[LuggMarkerAnnotationView alloc] initWithAnnotation:annotation | ||
| reuseIdentifier:nil]; | ||
|
|
@@ -1225,6 +1240,66 @@ - (void)syncMarkerView:(LuggMarkerView *)markerView { | |
| [self markerViewDidUpdate:markerView]; | ||
| } | ||
|
|
||
| - (void)applyImageMarkerStyle:(LuggMarkerView *)markerView | ||
| annotationView:(MKAnnotationView *)annotationView { | ||
| CGFloat scale = markerView.scale; | ||
| CGPoint anchor = markerView.anchor; | ||
|
|
||
| UIImage *cached = markerView.cachedImage; | ||
| if (cached) { | ||
| UIImage *image = [self scaleUIImage:cached scale:scale]; | ||
| annotationView.image = image; | ||
| CGFloat w = image.size.width; | ||
| CGFloat h = image.size.height; | ||
| annotationView.bounds = CGRectMake(0, 0, w, h); | ||
| annotationView.centerOffset = | ||
| CGPointMake(w * (0.5 - anchor.x), h * (0.5 - anchor.y)); | ||
| annotationView.transform = | ||
| CGAffineTransformMakeRotation(markerView.rotate * M_PI / 180.0); | ||
| } else { | ||
| [self loadMarkerImageUri:markerView.imageUri | ||
| forMarkerView:markerView | ||
| annotationView:annotationView]; | ||
| } | ||
| } | ||
|
|
||
| - (void)loadMarkerImageUri:(NSString *)uri | ||
| forMarkerView:(LuggMarkerView *)markerView | ||
| annotationView:(MKAnnotationView *)annotationView { | ||
| NSURL *url = [NSURL URLWithString:uri]; | ||
| if (!url) return; | ||
|
|
||
| __weak LuggMarkerView *weakMarkerView = markerView; | ||
| __weak MKAnnotationView *weakAnnotationView = annotationView; | ||
| dispatch_async( | ||
| dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ | ||
| NSData *data = [NSData dataWithContentsOfURL:url]; | ||
| UIImage *image = data ? [UIImage imageWithData:data] : nil; | ||
| dispatch_async(dispatch_get_main_queue(), ^{ | ||
| LuggMarkerView *strongMarkerView = weakMarkerView; | ||
| MKAnnotationView *strongAnnotationView = weakAnnotationView; | ||
| if (!strongMarkerView || !strongAnnotationView || !image) return; | ||
| strongMarkerView.cachedImage = image; | ||
| [self applyImageMarkerStyle:strongMarkerView | ||
| annotationView:strongAnnotationView]; | ||
| }); | ||
|
Comment on lines
+1266
to
+1285
|
||
| }); | ||
| } | ||
|
|
||
| - (UIImage *)scaleUIImage:(UIImage *)image scale:(CGFloat)scale { | ||
| if (scale == 1.0) return image; | ||
| CGSize size = | ||
| CGSizeMake(image.size.width * scale, image.size.height * scale); | ||
| UIGraphicsImageRendererFormat *format = | ||
| [UIGraphicsImageRendererFormat defaultFormat]; | ||
| format.scale = image.scale; | ||
| UIGraphicsImageRenderer *renderer = | ||
| [[UIGraphicsImageRenderer alloc] initWithSize:size format:format]; | ||
| return [renderer imageWithActions:^(UIGraphicsImageRendererContext *ctx) { | ||
| [image drawInRect:CGRectMake(0, 0, size.width, size.height)]; | ||
| }]; | ||
| } | ||
|
|
||
| - (void)applyMarkerStyle:(LuggMarkerView *)markerView | ||
| annotationView:(MKAnnotationView *)annotationView { | ||
| annotationView.transform = CGAffineTransformIdentity; | ||
|
|
@@ -1298,6 +1373,11 @@ - (void)updateAnnotationViewFrame:(AppleMarkerAnnotation *)annotation { | |
| if (!annotationView || !markerView) | ||
| return; | ||
|
|
||
| if (markerView.hasImageUri && !markerView.hasCustomView) { | ||
| [self applyImageMarkerStyle:markerView annotationView:annotationView]; | ||
| return; | ||
| } | ||
|
|
||
| [self applyMarkerStyle:markerView annotationView:annotationView]; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
cachedis present,scaleBitmap(cached, markerView.scale)allocates a new scaled bitmap every sync. SincesyncMarkerViewcan run frequently even whenscalehasn’t changed, this can create avoidable allocations and GC pressure. Consider caching the scaled bitmap/descriptor per (uri, scale) or only rescaling whenscalechanges.