箭头锚点在swift中没有正确显示

时间:2015-03-25 15:15:14

标签: ios swift

This is how anchor points now showing这是我用来绘制箭头并为其添加锚点的代码。但是我们可以在不同方向添加箭头,因为这个原因锚点错位。有没有人知道如何在箭头的起点和箭头的终点正确放置这些锚点。

//
//  AnnotationArrow.swift
//  
//
//  Created by Alvin Varghese on 10/Mar/15.
//  Copyright (c) 2015![enter image description here][2]. All rights reserved.
//

import UIKit

protocol _Annotation_ARROW_PROTOCOL
{
    func valuesFromArrowSubClass(instance : AnnotationArrow)
}

class AnnotationArrow: UIView
{
    //MARK: Global Variables

    var startingPoint : CGPoint = CGPoint()
    var endingPoint : CGPoint = CGPoint()
    var arrowLength : CGFloat = CGFloat()
    var arrowPath : UIBezierPath = UIBezierPath()
    var selectedInBox_Activated_Anchor_Points = false

    var delegate : _Annotation_ARROW_PROTOCOL!

    //MARK: For resizing

    var kUserResizableViewDefaultMinWidth = 40.0
    var kUserResizableViewDefaultMinHeight  = 40.0
    var kUserResizableViewInteractiveBorderSize = 10.0

    //MARK: initFrame

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

    //MARK: initCoder

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

    func passingValues(startingPointValue : CGPoint, endingPointValue : CGPoint)
    {
        self.startingPoint = startingPointValue
        self.endingPoint = endingPointValue

        var xDistance : CGFloat = self.endingPoint.x - self.startingPoint.x
        var yDistance : CGFloat = self.endingPoint.y - self.startingPoint.y

        self.arrowLength = sqrt((xDistance * xDistance) + (yDistance * yDistance))
    }

    //MARK: drawRect

    override func drawRect(rect: CGRect)
    {
        var tailWidth : CGFloat = max(4.0, self.arrowLength * 0.07)
        var headLength : CGFloat = max(self.arrowLength / 3.0, 10.0)
        var headWidth : CGFloat = headLength * 0.9
        var strokeWidth : CGFloat = max(1.0, tailWidth * 0.25)

        self.layer.shadowRadius = max(4.0, tailWidth)

        self.arrowPath = self.bezierPathWithArrowFromPoint(self.startingPoint, endPoint: self.endingPoint, tailWidth: tailWidth, headWidth: headWidth, headLength: headLength)

        self.arrowPath.fill()
        self.arrowPath.stroke()
        self.arrowPath.lineWidth = strokeWidth
        self.layer.shadowPath  = self.arrowPath.CGPath

        if self.selectedInBox_Activated_Anchor_Points
        {
            // Starting the code for - ResizableView anchor points

            var color : UIColor = UIColor.greenColor()

            var context : CGContextRef = UIGraphicsGetCurrentContext()
            CGContextSaveGState(context)

            // 1 -  Drawing the bounding box

            CGContextSetFillColorWithColor(context, color.CGColor)
            CGContextSetStrokeColorWithColor(context, color.CGColor)
            CGContextMoveToPoint(context, self.startingPoint.x, self.startingPoint.y)
            CGContextAddLineToPoint(context, self.endingPoint.x, self.endingPoint.y )
            CGContextSetLineWidth(context, 2.0)
            CGContextStrokePath(context)
            CGContextSetStrokeColorWithColor(context, color.CGColor)

            // 2 -  Calculate the bounding boxes for each of the anchor points.

            var startingSectionRect : CGRect  = CGRectMake(self.startingPoint.x, self.startingPoint.y, 20.0, 20.0)

            var endingSectionRect : CGRect = CGRectMake(self.endingPoint.x, self.endingPoint.y, 20.0, 20.0)

            // 3 -  Create the gradient to paint the anchor points.

            var colors : [CGFloat] = [1.0, 1.0]
            var baseSpace : CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()
            var gradient : CGGradientRef = CGGradientCreateWithColorComponents(baseSpace, colors, nil, 2)

            // 4 - Set up the stroke for drawing the border of each of the anchor points.

            CGContextSetLineWidth(context, 2.0)
            CGContextSetShadow(context, CGSizeMake(0.5, 0.5), 1)
            CGContextSetStrokeColorWithColor(context, color.CGColor)

            // 5 - Fill each anchor point using the gradient, then stroke the border.

            var allPoints : [CGRect] = [ startingSectionRect, endingSectionRect]

            for index in 0..<2
            {
                var currentPoint : CGRect = allPoints[index]
                CGContextSaveGState(context)
                CGContextAddEllipseInRect(context, currentPoint)
                CGContextClip(context)

                var startPoint : CGPoint = CGPointMake(CGRectGetMidX(currentPoint), CGRectGetMinY(currentPoint))

                var endPoint : CGPoint = CGPointMake(CGRectGetMidX(currentPoint), CGRectGetMaxY(currentPoint))


                CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0)
                CGContextRestoreGState(context)
                UIColor.greenColor().setFill()

                //  CGContextStrokeEllipseInRect(context, CGRectInset(currentPoint, 1, 1))
                CGContextFillEllipseInRect(context, currentPoint)
            }
            // Restoring state to most recently saved state
            CGContextRestoreGState(context)
        }
    }


    //MARK: hitTest

    override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView?
    {
        if self.arrowPath.containsPoint(point)
        {
            self.selectedInBox_Activated_Anchor_Points  = true
            self.setNeedsDisplay()
            self.delegate.valuesFromArrowSubClass(self)
            return self
        }

        var boundingBox : CGRect = self.arrowPath.bounds

        if ((boundingBox.size.width < 80 || boundingBox.size.height < 80) && CGRectContainsPoint(boundingBox, point))
        {
            self.selectedInBox_Activated_Anchor_Points = true
            self.setNeedsDisplay()
            self.delegate.valuesFromArrowSubClass(self)
            return self
        }

        self.selectedInBox_Activated_Anchor_Points  = false
        self.setNeedsDisplay()
        return nil
    }


    //MARK: Creating Path

    func bezierPathWithArrowFromPoint(startingPoint : CGPoint, endPoint : CGPoint, tailWidth : CGFloat, headWidth : CGFloat, headLength : CGFloat) -> UIBezierPath
    {

        var length = hypotf( Float(endPoint.x) - Float(startingPoint.x) , Float(endPoint.y) - Float(startingPoint.y))

        var tailLength : CGFloat = CGFloat(length) - headLength

        var points = [CGPointMake(0, tailWidth / 2), CGPointMake(tailLength, tailWidth / 2), CGPointMake(tailLength, headWidth / 2), CGPointMake(CGFloat(length), 0), CGPointMake(tailLength, (-headWidth) / 2), CGPointMake(tailLength, (-tailWidth) / 2 ), CGPointMake(0, (-tailWidth) / 2)]

        var cosine : CGFloat = (endPoint.x - startingPoint.x) / CGFloat(length)
        var sine : CGFloat = (endPoint.y - startingPoint.y) / CGFloat(length)
        var transform : CGAffineTransform = CGAffineTransform(a: cosine, b: sine, c: -sine, d: cosine, tx: startingPoint.x, ty: startingPoint.y)

        var cgPath : CGMutablePathRef = CGPathCreateMutable()
        CGPathAddLines(cgPath, &transform, points, (UInt)(points.count))
        CGPathCloseSubpath(cgPath)

        var bezierPath : UIBezierPath = UIBezierPath(CGPath: cgPath)
        bezierPath.lineCapStyle = kCGLineCapRound
        bezierPath.lineJoinStyle = kCGLineJoinRound

        return bezierPath
    }

    //MARK: UITouch Methods

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent)
    {
        var touch : UITouch = touches.anyObject() as UITouch


    }

    override func touchesMoved(touches: NSSet, withEvent event: UIEvent)
    {
        var touch : UITouch = touches.allObjects.last as UITouch
        var point = touch.locationInView(self.superview)

    }

    override func touchesEnded(touches: NSSet, withEvent event: UIEvent)
    {
    }

    override func touchesCancelled(touches: NSSet!, withEvent event: UIEvent!)
    {
    }
}

1 个答案:

答案 0 :(得分:2)

在绘制时,您正在考虑将您的点作为矩形:

var startingSectionRect : CGRect  = CGRectMake(self.startingPoint.x, self.startingPoint.y, 20.0, 20.0)

然后用椭圆(圆圈)填充此矩形。这显然是错的,因为你感兴趣的一点是留在左上角,而你想要它在中心:

let pointSize = 20.0
var startingSectionRect = CGRectMake(self.startingPoint.x - pointSize / 2.0, self.startingPoint.y - pointSize / 2.0, pointSize, pointSize)