summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-06-05 16:56:37 -0700
committerMinh Nguyễn <mxn@1ec5.org>2017-07-05 18:32:59 -0700
commitcc1f1a1e0bd4801fa3e079c723955f5a800c8bd6 (patch)
tree4fcff5717d91e7fb448c1043964e56020bfb4c67
parentba60e9b94cc2b6f106d15677d20f6cf796b42327 (diff)
downloadqtlocation-mapboxgl-cc1f1a1e0bd4801fa3e079c723955f5a800c8bd6.tar.gz
[ios] Annotation view degrees of freedom
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.
-rw-r--r--platform/ios/Mapbox.playground/Contents.swift2
-rw-r--r--platform/ios/app/MBXViewController.m6
-rw-r--r--platform/ios/src/MGLAnnotationView.h86
-rw-r--r--platform/ios/src/MGLAnnotationView.mm59
4 files changed, 97 insertions, 56 deletions
diff --git a/platform/ios/Mapbox.playground/Contents.swift b/platform/ios/Mapbox.playground/Contents.swift
index 8f4c574fc1..b1150a25b3 100644
--- a/platform/ios/Mapbox.playground/Contents.swift
+++ b/platform/ios/Mapbox.playground/Contents.swift
@@ -118,7 +118,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)
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 2fb38a5350..f7c20430d9 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -1711,7 +1711,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
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];
// Note that having two long press gesture recognizers on overlapping
@@ -1720,9 +1720,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
// method in this class to make draggable annotation views play nice.
annotationView.draggable = YES;
- // 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 force annotation view to maintain a constant size when
// the map is tilted. By default, annotation views will shrink and grow
diff --git a/platform/ios/src/MGLAnnotationView.h b/platform/ios/src/MGLAnnotationView.h
index 2a1a118d76..ce0203aaf7 100644
--- a/platform/ios/src/MGLAnnotationView.h
+++ b/platform/ios/src/MGLAnnotationView.h
@@ -37,6 +37,57 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
};
/**
+ 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
object that corresponds to the `MGLAnnotation` protocol. When an annotation’s
@@ -126,8 +177,14 @@ 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
+<<<<<<< HEAD
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.
+
+>>>>>>> 8d2bb2d42... [ios] Annotation view degrees of freedom
If you define distinctly different types of annotations (with distinctly
different annotation views to go with them), you can differentiate between the
annotation types by specifying different reuse identifiers for each one.
@@ -155,19 +212,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.
+ An option that specifies the annotation view’s degrees of freedom.
- 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.
+ 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
@@ -186,19 +237,6 @@ typedef NS_ENUM(NSUInteger, MGLAnnotationViewDragState) {
*/
@property (nonatomic, assign) BOOL scalesWithViewingDistance;
-/**
- A Boolean value that determines whether the annotation view rotates together
- with the map.
-
- When the value of this property is `YES` and the map is rotated, the annotation
- view rotates. This is also the behavior of `MGLAnnotationImage` objects. When the
- value of this property is `NO` the annotation has its rotation angle fixed.
-
- The default value of this property is `NO`. Set this property to `YES` if the
- view’s rotation is important.
- */
-@property (nonatomic, assign) BOOL rotatesToMatchCamera;
-
#pragma mark Managing the Selection State
/**
diff --git a/platform/ios/src/MGLAnnotationView.mm b/platform/ios/src/MGLAnnotationView.mm
index 94d0649413..6d38dc41c0 100644
--- a/platform/ios/src/MGLAnnotationView.mm
+++ b/platform/ios/src/MGLAnnotationView.mm
@@ -53,8 +53,12 @@
_reuseIdentifier = [decoder decodeObjectOfClass:[NSString class] forKey:@"reuseIdentifier"];
_annotation = [decoder decodeObjectOfClass:[NSObject class] forKey:@"annotation"];
_centerOffset = [decoder decodeCGVectorForKey:@"centerOffset"];
+ NSInteger freeAxes = [decoder decodeIntegerForKey:@"freeAxes"];
+ if (freeAxes < 0 || freeAxes > MGLAnnotationViewBillboardAxisAll) {
+ return nil;
+ }
+ _freeAxes = freeAxes;
_scalesWithViewingDistance = [decoder decodeBoolForKey:@"scalesWithViewingDistance"];
- _rotatesToMatchCamera = [decoder decodeBoolForKey:@"rotatesToMatchCamera"];
_selected = [decoder decodeBoolForKey:@"selected"];
_enabled = [decoder decodeBoolForKey:@"enabled"];
self.draggable = [decoder decodeBoolForKey:@"draggable"];
@@ -67,8 +71,8 @@
[coder encodeObject:_reuseIdentifier forKey:@"reuseIdentifier"];
[coder encodeObject:_annotation forKey:@"annotation"];
[coder encodeCGVector:_centerOffset forKey:@"centerOffset"];
+ [coder encodeInteger:_freeAxes forKey:@"freeAxes"];
[coder encodeBool:_scalesWithViewingDistance forKey:@"scalesWithViewingDistance"];
- [coder encodeBool:_rotatesToMatchCamera forKey:@"rotatesToMatchCamera"];
[coder encodeBool:_selected forKey:@"selected"];
[coder encodeBool:_enabled forKey:@"enabled"];
[coder encodeBool:_draggable forKey:@"draggable"];
@@ -111,8 +115,7 @@
center.y += _centerOffset.dy;
super.center = center;
- [self updateScaleTransformForViewingDistance];
- [self updateRotateTransform];
+ [self updateTransform];
}
- (void)setScalesWithViewingDistance:(BOOL)scalesWithViewingDistance
@@ -120,16 +123,36 @@
if (_scalesWithViewingDistance != scalesWithViewingDistance)
{
_scalesWithViewingDistance = scalesWithViewingDistance;
- [self updateScaleTransformForViewingDistance];
+ [self updateTransform];
+ }
+}
+
+- (void)setFreeAxes:(MGLAnnotationViewBillboardAxis)freeAxes
+{
+ if (_freeAxes != freeAxes)
+ {
+ _freeAxes = freeAxes;
+ [self updateTransform];
}
}
-- (void)updateScaleTransformForViewingDistance
+- (void)updateTransform
{
- if (self.scalesWithViewingDistance == NO || self.dragState == MGLAnnotationViewDragStateDragging) return;
+ if (self.dragState == MGLAnnotationViewDragStateDragging) return;
+ CATransform3D t = CATransform3DIdentity;
+ MGLMapCamera *camera = self.mapView.camera;
+ if (camera.pitch >= 0 && (self.freeAxes & MGLAnnotationViewBillboardAxisX))
+ {
+ 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);
- if (superviewHeight > 0.0) {
+ if ( ! self.scalesWithViewingDistance && superviewHeight > 0.0) {
// Find the maximum amount of scale reduction to apply as the view's center moves from the top
// of the superview to the bottom. For example, if this view's center has moved 25% of the way
// from the top of the superview towards the bottom then the maximum scale reduction is 1 - .25
@@ -161,26 +184,6 @@
}
}
-- (void)setRotatesToMatchCamera:(BOOL)rotatesToMatchCamera
-{
- if (_rotatesToMatchCamera != rotatesToMatchCamera)
- {
- _rotatesToMatchCamera = rotatesToMatchCamera;
- [self updateRotateTransform];
- }
-}
-
-- (void)updateRotateTransform
-{
- if (self.rotatesToMatchCamera == NO) return;
-
- CGFloat directionRad = self.mapView.direction * M_PI / 180.0;
- CATransform3D newRotateTransform = CATransform3DMakeRotation(-directionRad, 0, 0, 1);
- self.layer.transform = CATransform3DConcat(CATransform3DIdentity, newRotateTransform);
-
- _lastAppliedRotateTransform = newRotateTransform;
-}
-
#pragma mark - Draggable
- (void)setDraggable:(BOOL)draggable