如何对一张图片打Tag标签

来源:互联网 发布:java多线程同步和死锁 编辑:程序博客网 时间:2024/04/29 15:08

import UIKit


@objc public protocol QfWaveLayerDelegate : NSObjectProtocol {

    func layerDidFinishAnimation()

}



let QfWaveLayerDuration = 0.8

let QfWaveLayerNumberOfWaves = 2

let QfWaveLayerSpawnInterval = 0.65

let QfWaveLayerSpawnSize : CGFloat = 4.0

let QfWaveLayerScaleFactor : CGFloat = 4.0

let QfWaveLayerShadowRadius : CGFloat = 2.0


public classQfWaveLayer :CALayer {

    public weak var parentView :QfWaveLayerDelegate? =nil

    private var _scaleAnimation :CABasicAnimation!

    private var _opacityAnimation :CABasicAnimation!

    

    public overridefunc drawInContext(ctx: CGContext!) {

        CGContextSetRGBStrokeColor(ctx,0, 0,0, 1.0)

        CGContextSetLineWidth(ctx,1.5)

        let rect =CGRectMake(self.bounds.size.width/ 2- QfWaveLayerSpawnSize/ 2,self.bounds.size.height/ 2- QfWaveLayerSpawnSize/ 2,QfWaveLayerSpawnSize, QfWaveLayerSpawnSize)

        println(rect)

        CGContextStrokeEllipseInRect(ctx, rect)

    }

    

    public func startAnimation() {

        self.addAnimation(self.scaleAnimation(), forKey:"scale")

        self.addAnimation(self.opacityAnimation(), forKey:"opacity")

    }

    

    public func scaleAnimation() ->CABasicAnimation! {

        if self._scaleAnimation ==nil {

            self._scaleAnimation =CABasicAnimation(keyPath: "transform.scale")

            self._scaleAnimation.duration =RyxWaveLayerDuration

            self._scaleAnimation.delegate =self

            self._scaleAnimation.repeatCount =0

            self._scaleAnimation.removedOnCompletion =false

            self._scaleAnimation.fillMode =kCAFillModeForwards

            self._scaleAnimation.toValue =QfWaveLayerScaleFactor

        }

        returnself._scaleAnimation

    }

    

    public func opacityAnimation() ->CABasicAnimation! {

        ifself._opacityAnimation ==nil {

            self._opacityAnimation =CABasicAnimation(keyPath: "opacity")

            self._opacityAnimation.duration =QfWaveLayerDuration

            self._opacityAnimation.repeatCount =0

            self._opacityAnimation.removedOnCompletion =false

            self._opacityAnimation.fillMode =kCAFillModeForwards

            self._opacityAnimation.toValue =0

        }

        returnself._opacityAnimation

    }

    

    public overrideinit() {

        super.init()

    }

    

    public requiredinit(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

    }

    

    public overridefunc animationDidStop(anim: CAAnimation!, finished flag:Bool) {

        self.parentView?.layerDidFinishAnimation()

        (dispatch_get_main_queue(),2) ~>> {

            self.startAnimation()

        }

    }

}


public class QfWaveAnimationView :UIView, QfWaveLayerDelegate {

    private var wavesSpawned =0

    private var wavesDone =0

    

    private var waveLayer :QfWaveLayer?

    private var timer :NSTimer? = nil

    deinit {

        self.timer?.invalidate()

        for layer inself.layer.sublayers {

            if layer isQfWaveLayer {

                (layer as QfWaveLayer).parentView = nil

            }

        }

    }

    

    public class func waveAnimation(position: CGPoint, view: UIView?) -> QfWaveAnimationView {

        let av = QfWaveAnimationView(frame:CGRectMake(0, 0,100, 100))

        av.center = position

        view?.addSubview(av)

        return av

    }

    

    public overrideinit(frame: CGRect) {

        super.init(frame: frame)

        let wave = RyxWaveLayer()

        wave.bounds =CGRectMake(0,0, QfWaveLayerSpawnSize+ QfWaveLayerShadowRadius+ 2,QfWaveLayerSpawnSize +QfWaveLayerShadowRadius +2)

        wave.position = CGPointMake(self.bounds.size.width/ 2, self.bounds.size.height/ 2)

        wave.shadowColor =UIColor.yellowColor().CGColor

        wave.shadowOffset =CGSizeMake(0,0)

        wave.shadowOpacity = 1.0

        wave.shadowRadius =QfWaveLayerShadowRadius

        wave.parentView = self

        self.layer.addSublayer(wave)

        self.waveLayer = wave

        self.spawnWave()

        ifQfWaveLayerNumberOfWaves > 1 {

            var spawnInterval = QfWaveLayerSpawnInterval

            if spawnInterval > QfWaveLayerDuration * 1.25 {

                spawnInterval = QfWaveLayerDuration *1.25

            }

            self.timer =NSTimer.scheduledTimerWithTimeInterval(spawnInterval, target:self, selector: Selector("spawnWave"), userInfo:nil, repeats: true)

        }

    }

    

    public requiredinit(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

    }

    

    public func spawnWave() {

        self.waveLayer!.setNeedsDisplay()

        self.waveLayer!.startAnimation()

        self.wavesSpawned++

        ifself.wavesSpawned ==QfWaveLayerNumberOfWaves {

            self.timer?.invalidate()

            self.timer =nil

        }

    }

    

    public func layerDidFinishAnimation() {

        self.wavesDone++

        ifself.wavesDone ==self.wavesSpawned {

            self.wavesDone =0

        }

    }

}


public class QfTagLabel :UILabel {

    

    public var tagInfo :RyxTag? = nil

    

    public overrideinit(frame: CGRect) {

        super.init(frame: frame)

    }

    

    public requiredinit(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

    }

    

    public overridefunc drawTextInRect(rect: CGRect) {

        let insets = UIEdgeInsets(top:5, left: 5, bottom: 5, right: 5)

        super.drawTextInRect(UIEdgeInsetsInsetRect(rect, insets))

    }

    

    public overridefunc drawRect(rect: CGRect) {

        super.drawRect(rect)

    }

    

    public overridefunc drawLayer(layer: CALayer!, inContext ctx:CGContext!) {

        super.drawLayer(layer, inContext: ctx)

    }

}


private enum RSPopLabelArrowType :Int {

    case Left = 0

    case Right = 1

}


private let ArrowPointCount =7


private extension UIBezierPath {

    private class func arrowFromPoint(startPoint: CGPoint, endPoint:CGPoint, tailWidth: CGFloat, headWidth:CGFloat, headLength: CGFloat) -> UIBezierPath! {

        

        func getAxisAlignedArrowPoints(length:CGFloat, tailWidth: CGFloat, headWidth:CGFloat, headLength: CGFloat) -> [CGPoint] {

            var points = [CGPoint](count:ArrowPointCount, repeatedValue: CGPointZero)

            let tailLength = length - headLength

            points[0] = CGPointMake(0, tailWidth/ 2)

            points[1] = CGPointMake(tailLength, tailWidth/ 2);

            points[2] = CGPointMake(tailLength, headWidth/ 2);

            points[3] = CGPointMake(length,0);

            points[4] = CGPointMake(tailLength,-headWidth / 2);

            points[5] = CGPointMake(tailLength,-tailWidth / 2);

            points[6] = CGPointMake(0,-tailWidth / 2);

            return points

        }

        

        func transform(startPoint: CGPoint, endPoint: CGPoint, length: CGFloat) -> CGAffineTransform {

            let cosine = (endPoint.x- startPoint.x) / length

            let sine = (endPoint.y- startPoint.y) / length

            return CGAffineTransformMake(cosine, sine,-sine, cosine, startPoint.x, startPoint.y)

        }

        let length = CGFloat(hypotf(Float(endPoint.x- startPoint.x), Float(endPoint.y - startPoint.y)))

        var points = getAxisAlignedArrowPoints(length, tailWidth, headWidth, headLength)

        var transformData = transform(startPoint, endPoint, length)

        let path =CGPathCreateMutable()

        withUnsafePointer(&transformData, { (td) ->Void in

            CGPathAddLines(path, td, points,UInt(points.count))

        })

        CGPathCloseSubpath(path)

        let uiPath = UIBezierPath(CGPath: path)

        return uiPath

    }

    

    private class func arrow(startPoint: CGPoint, endPoint: CGPoint, headWidth: CGFloat, headLength: CGFloat) -> UIBezierPath {

        return arrowFromPoint(startPoint, endPoint: endPoint, tailWidth: headWidth, headWidth: headWidth, headLength: headLength)

    }

}


public class QfArrowView :UIView {

    private var label =QfTagLabel(frame: CGRectZero)

    public var tipPoint =CGPointZero

    private var tipSize =12

    privatevar arrowType : RSPopLabelArrowType = .Left

    private var targetFrame =CGRectZero

    private var bgImageView =UIImageView()

    private var bgImageView2 =UIImageView()

    private var shapeLayer =CAShapeLayer()

    

    private class var tipPadding : CGFloat {

        get {

            return 8.0

        }

    }

    

    private class var cornerRadius : CGFloat {

        get {

            return 6.0

        }

    }

    

    lazy public var labelColor = UIColor(white: 0.0, alpha:0.75)

    lazy public var labelTextColor = UIColor.whiteColor()

    lazy public var labelTextHightlightColor = UIColor.whiteColor()

    

    lazy public var labelFont : UIFont = {

        returnUIFont.systemFontOfSize(12)

    }()

    

    @IBInspectable public var text : String? {

        get {

            return self.label.text

        }

        set {

            self.label.text = newValue

        }

    }

    

    public overridefunc awakeFromNib() {

        super.awakeFromNib()

        self.shapeLayer.fillRule =kCAFillRuleNonZero

        self.layer.insertSublayer(self.shapeLayer, atIndex:0)

    }

    

    public init(text:String) {

        super.init(frame:CGRectZero)

        self.label.text = text

        self.shapeLayer.fillRule =kCAFillRuleNonZero

        self.layer.insertSublayer(self.shapeLayer, atIndex:0)

    }

    

    public overrideinit(frame: CGRect) {

        super.init(frame: frame)

        self.shapeLayer.fillRule =kCAFillRuleNonZero

        self.layer.insertSublayer(self.shapeLayer, atIndex:0)

        self.addSubview(bgImageView2)

        self.addSubview(bgImageView)

    }

    

    public requiredinit(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

        self.shapeLayer.fillRule =kCAFillRuleNonZero

        self.layer.insertSublayer(self.shapeLayer, atIndex:0)

    }

    

    public class var arrowSize : CGFloat {

        get {

            return 8

        }

    }

    

    public func setupApperance() {

        self.backgroundColor =UIColor.clearColor()

        self.label.textAlignment = .Left

        self.label.numberOfLines =0

        self.label.text =text

        self.addSubview(self.label)

        

        self.label.textColor =self.labelTextColor

        self.label.font =self.labelFont

        let maxWidth =UIScreen.mainScreen().applicationFrame.size.width* 0.8

        let maxHeight =UIScreen.mainScreen().applicationFrame.size.height* 0.8

        let attributedText = NSAttributedString(string: self.label.text!, attributes: [NSFontAttributeName:self.labelFont])

        var rect = attributedText.boundingRectWithSize(CGSizeMake(maxWidth,CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, context:nil)

        var minWidth = min(rect.size.width+ QfArrowView.arrowSize, 180)

        var minHeigth = min(rect.size.height, maxHeight)

        self.label.frame =CGRectMake(QfArrowView.arrowSize,0, minWidth, minHeigth)

        self.label.sizeToFit()

        self.targetFrame =self.label.frame

        let height = self.targetFrame.size.height+ CGFloat(self.tipSize *2)

        self.frame =CGRectMake(self.tipPoint.x, (self.tipPoint.y- height / 2) , minWidth+ QfArrowView.arrowSize + 5, height)

        self.label.frame =CGRectMake(QfArrowView.arrowSize,0, minWidth + 5, height)

        return                                                               

    }

    

    public overridefunc layoutSubviews() {

        super.layoutSubviews()

        self.setupApperance()


    }

    private func checkLeft() ->Bool {

        let width =UIScreen.mainScreen().applicationFrame.width

        if self.arrowType== .Left {

            if self.tipPoint.x+ self.fram  e.width > width {

                return false

            }

            return true

        }

        return false

    }

    

    private func checkRight() ->Bool {

        ifself.arrowType== .Right {

            if self.tipPoint.x >self.frame.width {

                return false

            }

            return true

        }

        return false

    }

    

    private func bestArrowDirection() -> (RSPopLabelArrowType,CGFloat) {

        if self.checkLeft() {

            return (.Left,0)

        } else if self.checkRight() {

            return (.Right,0)

        }

        // check tipLocation...

        return {() -> (RSPopLabelArrowType,CGFloat) in

            let width =UIScreen.mainScreen().applicationFrame.width

            if self.tipPoint.x <= width/ 2 {

                return (.Left, width- self.tipPoint.x)

            }

            return (.Right, width- self.tipPoint.x)

            }()

    }

    

    public func popAtView(view:UIView) {

        if self.hidden ==false {

            return

        }

        var (arrowType, space) = self.bestArrowDirection()

        self.arrowType = arrowType

        if space ==0 {

            

        } else {

            

        }

    }

    

    

            

    public overridefunc drawRect(rect: CGRect) {

        //        super.drawRect(rect)

        var roundedRect = rect

        roundedRect.origin.y+= QfArrowView.tipPadding

        roundedRect.size.height-=QfArrowView.tipPadding * 2

        var viewBackgroundPath : UIBezierPath!

        

        if self.arrowType== .Left {

            viewBackgroundPath = UIBezierPath.arrow(roundedRect.rightCenter, endPoint: roundedRect.leftCenter, headWidth:25, headLength: QfArrowView.arrowSize)

        } else if self.arrowType == .Right {

            viewBackgroundPath = UIBezierPath.arrow(roundedRect.leftCenter, endPoint: roundedRect.rightCenter, headWidth:25, headLength: QfArrowView.arrowSize)

        }

        self.shapeLayer.path = viewBackgroundPath.CGPath

        self.shapeLayer.fillColor =self.labelColor.CGColor

        self.shapeLayer.strokeColor =UIColor.redColor().CGColor

    }

}


public class QfDraggableArrowView :QfArrowView {

    publicvar animationView : QfAnimationView =QfAnimationView()

    public var timer :NSTimer?

    public var showTime :NSTimeInterval =1.5

    private var isAnimation :Bool = false

    public requiredinit(coder aDecoder: NSCoder) {

        self.voluntaryHidden =false;

        super.init(coder: aDecoder)

    }

    

    public overrideinit(frame: CGRect) {

        self.voluntaryHidden =false;

        super.init(frame: frame)

        animationView = QfAnimationView(frame:self.bounds, image: nil)

        self.addSubview(animationView)

        self.voluntaryHidden =false

    }

    

    public var voluntaryHidden :Bool {

        

        willSet (newValue) {

            if self.voluntaryHidden ==true && newValue == true {

                self.stopTimer()

            }

            

            self.startTimer()

        }

        didSet {

            if self.voluntaryHidden ==true {

            } else {

                self.stopTimer()

            }

        }

    }

    

    public func startTimer() {

        if self.isAnimation ==true {

            return

        }

       self.timer =NSTimer.scheduledTimerWithTimeInterval(self.showTime, target:self, selector: Selector("hiddenArrowView"), userInfo:nil, repeats: false)

    }

    

    public func stopTimer() {

        if self.isAnimation ==true {

            return

        }

        self.hidden =false

        self.alpha =1.0

        self.timer?.invalidate()

        self.timer =nil

    }

    

    public func hiddenArrowView() {

        self.hidden =true

    }

    

     deinit {

        self.stopTimer()

    }

    

    public overrideinit(text: String) {

        self.voluntaryHidden =false

        super.init(text: text)

    }

    

    public overridefunc layoutSubviews() {

        super.layoutSubviews()

        animationView.frame =self.bounds

    }

    

    private var currentPoint =CGPointZero

    

    public overridefunc touchesBegan(touches: NSSet, withEvent event:UIEvent) {

        // Promote the touched view

        self.superview?.bringSubviewToFront(self)

        currentPoint = touches.anyObject()!.locationInView(self)

    }

    

    public overridefunc touchesMoved(touches: NSSet, withEvent event:UIEvent) {

        let activePoint = touches.anyObject()!.locationInView(self)

        var newPoint = CGPointMake(self.center.x+ (activePoint.x - currentPoint.x), self.center.y + (activePoint.y - currentPoint.y))

        let midPointX = CGRectGetMidX(self.bounds)

        if newPoint.x >self.superview!.bounds.size.width- midPointX {

            newPoint.x = self.superview!.bounds.size.width- midPointX

        } else if newPoint.x< midPointX {

            newPoint.x = midPointX

        }

        

        let midPointY = CGRectGetMidY(self.bounds)

        if newPoint.y >self.superview!.bounds.size.height- midPointY {

            newPoint.y = self.superview!.bounds.size.height- midPointY

        } else if newPoint.y< midPointY {

            newPoint.y = midPointY

        }

        self.center = newPoint

    }

    

    public overridefunc touchesEnded(touches: NSSet, withEvent event:UIEvent) {

        let activePoint = touches.anyObject()!.locationInView(self)

        var newPoint = CGPointMake(self.center.x+ (activePoint.x - currentPoint.x), self.center.y + (activePoint.y - currentPoint.y))

        self.willChangeValueForKey("tipPoint")

        self.tipPoint = newPoint

        self.didChangeValueForKey("tipPoint")

    }

}

0 0