Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Commit

Permalink
[ios] Annotation view degrees of freedom
Browse files Browse the repository at this point in the history
Replaced MGLAnnotationView’s flat property with a freeAxes property that allows 0–2 degrees of freedom (pitch and/or rotation).

Reformatted and copyedited MGLAnnotationView documentation. Removed the unnecessary custom getter on scalesWithViewingDistance.

Fixes #2528.
  • Loading branch information
1ec5 committed Jul 10, 2016
1 parent 86b3470 commit 8d2bb2d
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 21 deletions.
2 changes: 1 addition & 1 deletion platform/ios/Mapbox.playground/Contents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class MapDelegate: NSObject, MGLMapViewDelegate {
let av = PlaygroundAnnotationView(reuseIdentifier: "annotation")
av.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
av.centerOffset = CGVector(dx: -15, dy: -15)
av.flat = true
av.freeAxes = .X;
let centerView = UIView(frame: CGRectInset(av.bounds, 3, 3))
centerView.backgroundColor = UIColor.whiteColor()
av.addSubview(centerView)
Expand Down
8 changes: 4 additions & 4 deletions platform/ios/app/MBXViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -586,12 +586,12 @@ - (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAn
if (!annotationView)
{
annotationView = [[MBXAnnotationView alloc] initWithReuseIdentifier:MBXViewControllerAnnotationViewReuseIdentifer];
annotationView.frame = CGRectMake(0, 0, 10, 10);
annotationView.frame = CGRectMake(0, 0, 30, 30);
annotationView.backgroundColor = [UIColor whiteColor];

// uncomment to flatten the annotation view against the map when the map is tilted
// uncomment to lay the annotation view flat against the map when the map is tilted
// this currently causes severe performance issues when more than 2k annotations are visible
// annotationView.flat = YES;
// annotationView.freeAxes = MGLAnnotationViewBillboardAxisX;

// uncomment to make the annotation view draggable
// also note that having two long press gesture recognizers on overlapping views (`self.view` & `annotationView`) will cause weird behaviour
Expand All @@ -601,7 +601,7 @@ - (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAn
// uncomment to force annotation view to maintain a constant size when the map is tilted
// by default, annotation views will shrink and grow as the move towards and away from the
// horizon. Relatedly, annotations backed by GL sprites ONLY scale with viewing distance currently.
// annotationView.scalesWithViewingDistance = NO;
// annotationView.scalesWithViewingDistance = NO;
} else {
// orange indicates that the annotation view was reused
annotationView.backgroundColor = [UIColor orangeColor];
Expand Down
1 change: 1 addition & 0 deletions platform/ios/jazzy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ custom_categories:
- MGLAnnotationImage
- MGLAnnotationVerticalAlignment
- MGLAnnotationView
- MGLAnnotationViewBillboardAxis
- MGLAnnotationViewDragState
- MGLCalloutView
- MGLCalloutViewDelegate
Expand Down
70 changes: 58 additions & 12 deletions platform/ios/src/MGLAnnotationView.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,57 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
MGLAnnotationViewDragStateEnding,
};

/**
Options for locking the orientation of an `MGLAnnotationView` along one or more
axes for a billboard effect.
*/
typedef NS_OPTIONS(NSUInteger, MGLAnnotationViewBillboardAxis)
{
/**
Orients the annotation view such that its x-axis is always fixed with
respect to the map.
If this option is unset, the annotation view remains unchanged as the map’s
pitch increases, so that the view appears to stand upright on the tilted
map. If this option is set, the annotation view tilts as the map’s pitch
increases, so that the view appears to lie flat against the tilted map.
For example, you would set this option if the annotation view depicts an
arrow that should always point due south. You would unset this option if
the arrow should always point down towards the ground.
*/
MGLAnnotationViewBillboardAxisX = 0x1 << 0,

/**
Orients the annotation view such that its y-axis is always fixed with
respect to the map.
If this option is unset, the annotation view remains unchanged as the map
is rotated. If this option is set, the annotation view rotates as the map
rotates.
For example, you would set this option if the annotation view should be
aligned with a street, regardless of the direction from which the user
views the street.
*/
MGLAnnotationViewBillboardAxisY = 0x1 << 1,

/**
Orients the annotation view such that its z-axis is always fixed with
respect to the map.
Because `MGLMapView` does not support changes to its bank, or roll, this
option has no effect.
*/
MGLAnnotationViewBillboardAxisZ = 0x1 << 2,

/**
Orients the annotation view such that all three axes are always fixed with
respect to the map.
*/
MGLAnnotationViewBillboardAxisAll = (MGLAnnotationViewBillboardAxisX | MGLAnnotationViewBillboardAxisY | MGLAnnotationViewBillboardAxisZ),
};

/**
The `MGLAnnotationView` class is responsible for marking a point annotation
with a view. Annotation views represent an annotation object, which is an
Expand Down Expand Up @@ -98,7 +149,8 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
You specify the reuse identifier when you create the view. You use the
identifier later to retrieve an annotation view that was created previously but
which is currently unused because its annotation is not on-screen.
which is currently unused because its annotation does not lie within the map
view’s viewport.
If you define distinctly different types of annotations (with distinctly
different annotation views to go with them), you can differentiate between the
Expand Down Expand Up @@ -127,19 +179,13 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
@property (nonatomic) CGVector centerOffset;

/**
A Boolean value indicating whether the view lies flat against the map as it
tilts.
If this option is unset, the annotation view remains unchanged as the map’s
pitch increases, so that the view appears to stand upright on the tilted map.
If this option is set, the annotation view tilts as the map’s pitch increases,
so that the view appears to lie flat against the tilted map.
An option that specifies the annotation view’s degrees of freedom.
For example, you would set this option if the annotation view depicts an arrow
that should always point due south. You would unset this option if the arrow
should always point down towards the ground.
By default, none of the axes are free; in other words, the annotation view is
oriented like a billboard with respect to the x-, y-, and z-axes. See
`MGLAnnotationViewBillboardAxis` for available options.
*/
@property (nonatomic, assign, getter=isFlat) BOOL flat;
@property (nonatomic, assign) MGLAnnotationViewBillboardAxis freeAxes;

/**
A Boolean value that determines whether the annotation view grows and shrinks
Expand Down
13 changes: 9 additions & 4 deletions platform/ios/src/MGLAnnotationView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,15 @@ - (void)updateTransform
return;
}

self.layer.transform = CATransform3DIdentity;
CATransform3D t = CATransform3DIdentity;
MGLMapCamera *camera = self.mapView.camera;
if (self.flat)
if (camera.pitch >= 0 && (self.freeAxes & MGLAnnotationViewBillboardAxisX))
{
self.layer.transform = CATransform3DRotate(self.layer.transform, MGLRadiansFromDegrees(camera.pitch), 1.0, 0, 0);
t = CATransform3DRotate(t, MGLRadiansFromDegrees(camera.pitch), 1.0, 0, 0);
}
if (camera.heading >= 0 && (self.freeAxes & MGLAnnotationViewBillboardAxisY))
{
t = CATransform3DRotate(t, MGLRadiansFromDegrees(-camera.heading), 0.0, 0.0, 1.0);
}

CGFloat superviewHeight = CGRectGetHeight(self.superview.frame);
Expand All @@ -117,8 +121,9 @@ - (void)updateTransform
// reduction is then normalized for a scale of 1.0.
CGFloat pitchAdjustedScale = 1.0 - maxScaleReduction * pitchIntensity;

self.layer.transform = CATransform3DScale(self.layer.transform, pitchAdjustedScale, pitchAdjustedScale, 1);
t = CATransform3DScale(t, pitchAdjustedScale, pitchAdjustedScale, 1);
}
self.layer.transform = t;
}

#pragma mark - Draggable
Expand Down
4 changes: 4 additions & 0 deletions platform/ios/src/MGLMapView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4566,6 +4566,9 @@ - (void)updateAnnotationViews
[CATransaction begin];
[CATransaction setDisableActions:YES];

CLLocationDirection direction = self.direction;
CGFloat pitch = self.camera.pitch;

for (auto &pair : _annotationContextsByAnnotationTag)
{
CGRect viewPort = CGRectInset(self.bounds,
Expand All @@ -4588,6 +4591,7 @@ - (void)updateAnnotationViews

annotationView.center = [self convertCoordinate:annotationContext.annotation.coordinate toPointToView:self];
annotationView.mapView = self;

annotationContext.annotationView = annotationView;
}
}
Expand Down

0 comments on commit 8d2bb2d

Please sign in to comment.