简体   繁体   中英

Swift - how to animatedly draw line NOT rect? Can only draw rect?

I have looked around about this before but have yet to find an answer. I've been at this for a while and need to know how to animate a LINE as opposed to a rectangle.

From what I can see the animation is very different going from a stroke to a box. Just need some pointers here-

I have a border that is drawn on view load (not with an animation, it just draws it) here:

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

        let borderColor = self.hasError! ? kDefaultActiveColor : kDefaultErrorColor

        let textRect = self.textRectForBounds(rect)

        let context = UIGraphicsGetCurrentContext()
        let borderlines : [CGPoint] = [CGPointMake(0, CGRectGetHeight(textRect) - 1),
            CGPointMake(CGRectGetWidth(textRect), CGRectGetHeight(textRect) - 1)]

        if  self.enabled  {

            CGContextBeginPath(context);
            CGContextAddLines(context, borderlines, 2);
            CGContextSetLineWidth(context, 1.3);
            CGContextSetStrokeColorWithColor(context, borderColor.CGColor);
            CGContextStrokePath(context);

I got this from another answer and am trying to take it apart. I need the line to animate/grow out from its centre when the view loads, as in grow to the same width and size as it is drawn here but animated.

I do not know how to accomplish this, however another answer achieved the effect I need by setting the border to a size of zero here:

self.activeBorder = UIView(frame: CGRectZero)
self.activeBorder.backgroundColor = kDefaultActiveColor
//self.activeBorder.backgroundColor = kDefaultActiveBorderColor
self.activeBorder.layer.opacity = 0
self.addSubview(self.activeBorder)

and animating using:

self.borderlines.transform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1)
self.activeBorder.layer.opacity = 1

CATransaction.begin()
self.activeBorder.layer.transform = CATransform3DMakeScale(CGFloat(0.03), CGFloat(1.0), 1)
let anim2 = CABasicAnimation(keyPath: "transform")
let fromTransform = CATransform3DMakeScale(CGFloat(0.01), CGFloat(1.0), 1)
let toTransform = CATransform3DMakeScale(CGFloat(1.0), CGFloat(1.0), 1)
anim2.fromValue = NSValue(CATransform3D: fromTransform)
anim2.toValue = NSValue(CATransform3D: toTransform)
anim2.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
anim2.fillMode = kCAFillModeForwards
anim2.removedOnCompletion = false
self.activeBorder.layer.addAnimation(anim2, forKey: "_activeBorder")

CATransaction.commit()

This seems to be using entirely different code than my original drawRect and I don't know how to combine the two. Where am I going wrong here? How can I draw out from the centre my first border as I do the second, active border?

Use CAShapeLater , UIBezierPath and CABasicAnimation to animatedly draw line.

Here is the sample code:

class SampleView: UIView {

    override public func drawRect(rect: CGRect) {
        let leftPath = UIBezierPath()
        leftPath.moveToPoint(CGPointMake(CGRectGetMidX(frame), CGRectGetHeight(frame)))
        leftPath.addLineToPoint(CGPointMake(0, CGRectGetHeight(frame)))

        let rightPath = UIBezierPath()
        rightPath.moveToPoint(CGPointMake(CGRectGetMidX(frame), CGRectGetHeight(frame)))
        rightPath.addLineToPoint(CGPointMake(CGRectGetWidth(frame), CGRectGetHeight(frame)))

        let leftShapeLayer = CAShapeLayer()
        leftShapeLayer.path = leftPath.CGPath
        leftShapeLayer.strokeColor = UIColor.redColor().CGColor;
        leftShapeLayer.lineWidth = 1.3
        leftShapeLayer.strokeEnd = 0
        layer.addSublayer(leftShapeLayer)

        let rightShpaeLayer = CAShapeLayer()
        rightShpaeLayer.path = rightPath.CGPath
        rightShpaeLayer.strokeColor = UIColor.redColor().CGColor;
        rightShpaeLayer.lineWidth  = 1.3
        rightShpaeLayer.strokeEnd = 0
        layer.addSublayer(rightShpaeLayer)

        let drawLineAnimation = CABasicAnimation(keyPath: "strokeEnd")
        drawLineAnimation.toValue = NSNumber(float: 1)
        drawLineAnimation.duration = 1
        drawLineAnimation.fillMode = kCAFillModeForwards
        drawLineAnimation.removedOnCompletion = false

        leftShapeLayer.addAnimation(drawLineAnimation, forKey: nil)
        rightShpaeLayer.addAnimation(drawLineAnimation, forKey: nil)
    }

}

The code in viewDidLoad of ViewController

// ...
let sampleView = SampleView()
sampleView.frame = CGRectMake(10, 60, 240, 50)
sampleView.backgroundColor = UIColor.lightGrayColor()
view.addSubview(sampleView)

Here is the capture:

在此处输入图片说明

Note: If you run the code in iOS9 Simulator (I have not tested the earlier version), the animation may get blocked. Choose to run it in a real device or in iOS10 Simulator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM