diff --git a/src/ui-mapbox/index.ios.ts b/src/ui-mapbox/index.ios.ts index c977515..5f61a90 100755 --- a/src/ui-mapbox/index.ios.ts +++ b/src/ui-mapbox/index.ios.ts @@ -61,7 +61,6 @@ class MGLMapViewDelegateImpl extends NSObject implements MGLMapViewDelegate { private cameraChangedListener: (reason, animated?: boolean) => void; private cameraIdledListener: () => void; private userLocationRenderMode: any; - private userLocationAnnotationView: CustomUserLocationAnnotationView; /** * initialize with the mapReady callback @@ -100,7 +99,7 @@ class MGLMapViewDelegateImpl extends NSObject implements MGLMapViewDelegate { * set user location marker modes */ changeUserLocationRenderMode(userLocationRenderMode) { - this.userLocationAnnotationView.changeUserLocationRenderMode(userLocationRenderMode); + // nothing to do here } /** @@ -315,23 +314,6 @@ class MGLMapViewDelegateImpl extends NSObject implements MGLMapViewDelegate { } } - /** - * override the standard location marker - */ - mapViewViewForAnnotation(mapView: MGLMapView, annotation: MGLAnnotation): MGLAnnotationView { - if (Trace.isEnabled()) { - CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewViewForAnnotation() top'); - } - - if (annotation.isKindOfClass(MGLUserLocation.class())) { - this.userLocationAnnotationView = CustomUserLocationAnnotationView.alloc().init() as CustomUserLocationAnnotationView; - - return this.userLocationAnnotationView; - } - - return null; - } - mapViewRegionIsChangingWithReason(mapView: MGLMapView, reason: MGLCameraChangeReason) { if (Trace.isEnabled()) { CLog(CLogTypes.info, 'MGLMapViewDelegateImpl::mapViewRegionIsChanging()'); @@ -909,297 +891,6 @@ export class MapboxView extends MapboxViewBase { } } -/** - * a custom user location marker - * - * We want to add some behavior to the user location marker to visibly - * show the user when locations are being stored and when they are not. - * - * Sadly, it's not as easy under iOS as it is on Android. It involves - * creating a custom annotation view. - * - * @link https://docs.mapbox.com/ios/maps/examples/user-location-annotation/ - */ - -@NativeClass -class CustomUserLocationAnnotationView extends MGLUserLocationAnnotationView implements MGLUserLocationAnnotationView { - public size: number; - public dot: CALayer; - public arrow: CAShapeLayer; - - // may be NORMAL, COMPASS, or GPS. - - private userLocationRenderMode: string; - private renderModeChanged: boolean; - - /** - * init - * - * @link https://docs.nativescript.org/core-concepts/ios-runtime/HelloWorld - */ - - public init() { - this.size = 48; - super.initWithFrame(CGRectMake(0, 0, this.size, this.size)); - - this.renderModeChanged = true; - this.userLocationRenderMode = 'NORMAL'; - - return this; - } - - /** - * update - * - * The note from the Objective-C sample indicates this method may be called quite - * often so it needs to be kept lightweight. - */ - - update() { - if (CLLocationCoordinate2DIsValid(this.userLocation.coordinate)) { - // if it's the first time here, setup the layers that make up the - // location marker. - - if (!this.dot) { - this.drawNonTrackingLocationMarker(); - } - - if (this.userLocationRenderMode === 'GPS') { - this.updateHeading(); - } - } - } - - /** - * Draw the GPS tracking arrow. - * - * @link https://docs.nativescript.org/ns-framework-modules/color - */ - - drawTrackingLocationMarker() { - if (Trace.isEnabled()) { - CLog(CLogTypes.info, 'CustomerUserLocationAnnotatinView::drawTrackingLocationMarker()'); - } - - this.drawTrackingDot(); - this.drawArrow(); - } // end of setupLayers() - - /** - * draw the non-tracking marker - */ - - drawNonTrackingLocationMarker() { - if (Trace.isEnabled()) { - CLog(CLogTypes.info, 'CustomerUserLocationAnnotatinView::drawNonTrackingLocationMarker()'); - } - - this.drawNonTrackingDot(); - - if (this.arrow) { - this.arrow.removeFromSuperlayer(); - this.arrow = null; - } - } - - /** - * draw the tracking dot. - */ - - drawTrackingDot() { - this.size = 48; - - // we need to adjust the size of the bounds of the marker. The Tracking marker - // is larger than the non tracking marker. - - this.bounds = CGRectMake(0, 0, this.size, this.size); - - const dot = CALayer.layer(); - - dot.frame = this.bounds; - - // user corner radius to turn the layer into a circle - - dot.cornerRadius = this.size / 2; - dot.backgroundColor = this.tintColor.CGColor; - dot.borderWidth = 4; - - const whiteColor = new Color('#FFFFFF'); - dot.borderColor = whiteColor.ios.CGColor; - - if (!this.dot) { - this.layer.addSublayer(dot); - } else { - this.layer.replaceSublayerWith(this.dot, dot); - } - - // QUESTION: does GC catch this? - - this.dot = dot; - } - - /** - * draw the non-tracking dot. - */ - - drawNonTrackingDot() { - this.size = 24; - this.bounds = CGRectMake(0, 0, this.size, this.size); - const dot = CALayer.layer(); - - dot.frame = this.bounds; - - // user corner radius to turn the layer into a circle - - dot.cornerRadius = this.size / 2; - dot.backgroundColor = this.tintColor.CGColor; - - dot.borderWidth = 1; - - const whiteColor = new Color('#FFFFFF'); - dot.borderColor = whiteColor.ios.CGColor; - - if (!this.dot) { - this.layer.addSublayer(dot); - } else { - this.layer.replaceSublayerWith(this.dot, dot); - } - - // QUESTION: does GC catch this? - - this.dot = dot; - } - - /** - * draw an arrow - */ - - drawArrow() { - const arrow = CAShapeLayer.layer(); - - arrow.path = this.arrowPath(); - arrow.frame = CGRectMake(0, 0, this.size / 2, this.size / 2); - arrow.position = CGPointMake(CGRectGetMidX(this.dot.frame), CGRectGetMidY(this.dot.frame)); - arrow.fillColor = this.dot.borderColor; - - if (!this.arrow) { - this.layer.addSublayer(arrow); - } else { - this.layer.replaceSublayerWith(this.arrow, arrow); - } - - // QUESTION: Does GC catch this? - - this.arrow = arrow; - } - - /** - * update arrow heading - * - * @link https://docs.nativescript.org/core-concepts/ios-runtime/types/C-Functions - */ - - updateHeading() { - // just to avoid a possible race condition where the arrow isnt' drawn yet - - if (!this.arrow) { - return; - } - - if (typeof this.userLocation == 'undefined') { - return; - } - - if (typeof this.userLocation.heading == 'undefined' || this.userLocation.heading === null) { - return; - } - - if (typeof this.userLocation.heading.trueHeading == 'undefined' || this.userLocation.heading.trueHeading === null) { - return; - } - - if (this.userLocation.heading.trueHeading > 0) { - this.arrow.hidden = false; - - // get the difference between the map's current direction and the - // user's heading, then convert it from degrees to radians - // - // The original Objective-C example uses the inline C function MGLRadiansFromDegrees but because - // it's declared as inline it is not available for NativeScript. See linked article above. - - // let rotation : number = MGLRadiansFromDegrees( this.mapView.direction - this.userLocation.heading.trueHeading ); - - const degrees: number = this.mapView.direction - this.userLocation.heading.trueHeading; - - // in radians - - let rotation: number = (degrees * Math.PI) / 180; - - rotation = -rotation; - - // if the difference would be perceptible, rotate the arrow. - - if (fabs(rotation) > 0.01) { - // Disable implicit animations of this rotation, which reduces lag between updates - - CATransaction.begin(); - CATransaction.setDisableActions(true); - - this.arrow.setAffineTransform(CGAffineTransformRotate(CGAffineTransformIdentity, rotation)); - - CATransaction.commit(); - } - } else { - this.arrow.hidden = true; - } - } - - /** - * Calculate the vector path for an arrow - */ - - arrowPath() { - const max: number = this.size / 2; - const pad: number = 3; - - const top: CGPoint = CGPointMake(max * 0.5, 0); - const left: CGPoint = CGPointMake(0 + pad, max - pad); - const right: CGPoint = CGPointMake(max - pad, max - pad); - const center: CGPoint = CGPointMake(max * 0.5, max * 0.6); - - const bezierPath = UIBezierPath.bezierPath(); - bezierPath.moveToPoint(top); - bezierPath.addLineToPoint(left); - bezierPath.addLineToPoint(center); - - bezierPath.addLineToPoint(right); - bezierPath.addLineToPoint(top); - bezierPath.closePath(); - - return bezierPath.CGPath; - } - - /** - * change Render mode - * - * @param {string} renderMode - */ - - changeUserLocationRenderMode(renderMode) { - if (Trace.isEnabled()) { - CLog(CLogTypes.info, "CustomUserLocationAnnotatinView::changeUserLocationRenderMode(): changing mode to '" + renderMode + "'"); - } - - this.userLocationRenderMode = renderMode; - - if (renderMode === 'GPS') { - this.drawTrackingLocationMarker(); - } else { - this.drawNonTrackingLocationMarker(); - } - } -} // end of class CustomUserLocationAnnotationView - export class Mapbox extends MapboxCommon implements MapboxApi { // reference to the native mapbox API