iOS - How to animate the size of a subclassed MKAnnotationView?

173 views Asked by At

In my app, I'm using a subclassed MKAnnotationView to draw my own "Annotation" onto the MapView. Which is working fine.

What I want to have happen is when the function "didSelectAnnotationView" gets called in my MapViewController, it will animate the Annotation with springyness to a larger size. In my case the base size is CGSize(26, 26), and the larger size is CGSize(78, 78).

I've had a hell of a time just getting to where my code sits and I'm burned out to say the least. So where it stands right now, I'm not even implementing any animations, I'm just trying to get the damn thing to grow to the larger size correctly. What happens is when the "didSelect" function gets called and I call the "myPinView.animateSize(shouldGrow:, fromDrawRect:)" function to redraw everything and it does draw a larger Pin but it keeps the smaller Pin underneath everything.

Any help would be much appreciated.

class myPinView: MKAnnotationView {

  var outlineColor: UIColor = UIColor.orangeColor()
  var textSize: CGFloat = CGFloat(9.0)
  var lastTextString: String = ""
  var textLabel: UILabel = UILabel()
  var textString: String = "RG" {
    didSet {
      lastTextString = oldValue
    }
  }

  private var diameter: CGFloat = 0
  private var arcWidth: CGFloat = 0
  private var arcCenter: CGPoint = CGPointZero
  private var startAngle: CGFloat = 3 * pi / 4
  private var endAngle: CGFloat = pi / 4

  required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
  }

  override init(frame: CGRect) {
    super.init(frame: frame)
  }

  override init(annotation: MKAnnotation!, reuseIdentifier: String!) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
  }

override func drawRect(rect: CGRect) {
  super.drawRect(rect)

  drawPin(false, fromDrawRect: true)
}

func animateSize(shouldGrow: Bool, text: String) {

  if shouldGrow {
    textSize = 18.0
    textString = text
  } else {
    textSize = 9.0
    textString = lastTextString
  }

  drawPin(shouldGrow, fromDrawRect: false)

}

func drawPin(shouldGrow: Bool, fromDrawRect: Bool) {

  var b = bounds
  var boundsForDrawing: CGRect

  if shouldGrow {
    boundsForDrawing = CGRect(x: b.origin.x, y: b.origin.y, width:   b.size.width + 52, height: b.size.height + 52)
  } else {
    boundsForDrawing = CGRect(x: b.origin.x, y: b.origin.y, width: 26, height: 26)
  }

  diameter = min(boundsForDrawing.width, boundsForDrawing.height)
  arcWidth = diameter * CGFloat(0.7)
  arcCenter = CGPoint(x: boundsForDrawing.width/2, y: boundsForDrawing.height/2 - (diameter/2 * CGFloat(0.25)))

  var startXoffset = arcCenter.x - (sin(startAngle) * arcWidth/2)
  var startYoffset = arcCenter.y - (cos(startAngle) * arcWidth/2)

  var path = UIBezierPath(
    arcCenter: arcCenter,
    radius: arcWidth/2,
    startAngle: startAngle,
    endAngle: endAngle,
    clockwise: true)

  path.addQuadCurveToPoint(CGPointMake(arcCenter.x, boundsForDrawing.height/2 + diameter/2),
                                    controlPoint: CGPointMake(arcCenter.x, arcCenter.y + (arcWidth * CGFloat(0.7))))
  path.addQuadCurveToPoint(CGPointMake(startXoffset, startYoffset),
                                    controlPoint: CGPointMake(arcCenter.x, arcCenter.y + (arcWidth * CGFloat(0.7))))

  if fromDrawRect {
    layer.shadowColor = UIColor.blackColor().CGColor
    layer.shadowOpacity = 0.5
    layer.shadowOffset = CGSizeMake(0, 5.0)
    layer.anchorPoint = CGPoint(x: 0.5, y: 1.0)
  }

  var innerPath = UIBezierPath(
    arcCenter: arcCenter,
    radius: (arcWidth/2 * CGFloat(0.8)),
    startAngle: 0,
    endAngle: 2 * pi,
    clockwise: true)

  innerPath.lineWidth = CGFloat(1.0)

  var maskOuterLayer = CAShapeLayer()
  maskOuterLayer.path = path.CGPath
  maskOuterLayer.fillColor = outlineColor.CGColor


  var maskInnerLayer = CAShapeLayer()
  maskInnerLayer.path = innerPath.CGPath
  maskInnerLayer.fillColor = UIColor.clearColor().CGColor
  maskInnerLayer.strokeColor = UIColor.blackColor().CGColor

  textLabel.font = UIFont(name: "MarkerFelt-Thin", size: textSize)

  var textPointSize = textLabel.font.pointSize

  var lblStartPoint = CGPointMake(arcCenter.x - (sin(startAngle) * (arcWidth/2 * CGFloat(0.8))),
                                arcCenter.y - (cos(startAngle) * (arcWidth/2 * CGFloat(0.8))))
  var lblSize = CGSizeMake((sin(startAngle) * (arcWidth * CGFloat(0.8))),
                          (cos(startAngle) * (arcWidth * CGFloat(0.8))))

  textLabel.frame = CGRect(origin: lblStartPoint, size: lblSize)
  textLabel.center = arcCenter

  textLabel.text = textString
  textLabel.textColor = UIColor.blackColor()
  textLabel.backgroundColor = UIColor.clearColor()
  textLabel.adjustsFontSizeToFitWidth = true
  textLabel.textAlignment = NSTextAlignment.Center


  maskInnerLayer.addSublayer(textLabel.layer)
  maskOuterLayer.addSublayer(maskInnerLayer)

  if layer.sublayers?.count > 0 {
    layer.replaceSublayer(layer.sublayers[0] as! CAShapeLayer, with: maskOuterLayer)
  } else {
    layer.addSublayer(maskOuterLayer)
  }


  if shouldGrow {
    bounds.size = CGSize(width: 78, height: 78)
  } else {
    if !fromDrawRect {
      bounds.size = CGSize(width: 26, height: 26)
    }
  }
}

}
0

There are 0 answers