加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 如何用固定的开始到结束位置替换panGestureDidMove

发布时间:2020-12-14 05:24:24 所属栏目:百科 来源:网络整理
导读:我一直在使用UIPanGestureRecognizer来识别触摸,但我想用动画的固定开始到结束位置替换它.请参阅以下代码: panGestureDidMove: func panGestureDidMove(gesture: UIPanGestureRecognizer) { if gesture.state == .Ended || gesture.state == .Failed || ge
我一直在使用UIPanGestureRecognizer来识别触摸,但我想用动画的固定开始到结束位置替换它.请参阅以下代码:

panGestureDidMove:

func panGestureDidMove(gesture: UIPanGestureRecognizer) {  
if gesture.state == .Ended || gesture.state == .Failed || gesture.state == .Cancelled {

} else {
    let additionalHeight = max(gesture.translationInView(view).y,0)

    let waveHeight = min(additionalHeight * 0.6,maxWaveHeight)
    let baseHeight = minimalHeight + additionalHeight - waveHeight

    let locationX = gesture.locationInView(gesture.view).x

    layoutControlPoints(baseHeight: baseHeight,waveHeight: waveHeight,locationX: locationX)
    updateShapeLayer()
    }
}

layoutControlPoints:

private func layoutControlPoints(baseHeight baseHeight: CGFloat,waveHeight: CGFloat,locationX: CGFloat) {  
let width = view.bounds.width

let minLeftX = min((locationX - width / 2.0) * 0.28,0.0)
let maxRightX = max(width + (locationX - width / 2.0) * 0.28,width)

let leftPartWidth = locationX - minLeftX
let rightPartWidth = maxRightX - locationX

l3ControlPointView.center = CGPoint(x: minLeftX,y: baseHeight)
l2ControlPointView.center = CGPoint(x: minLeftX + leftPartWidth * 0.44,y: baseHeight)
l1ControlPointView.center = CGPoint(x: minLeftX + leftPartWidth * 0.71,y: baseHeight + waveHeight * 0.64)
cControlPointView.center = CGPoint(x: locationX,y: baseHeight + waveHeight * 1.36)
r1ControlPointView.center = CGPoint(x: maxRightX - rightPartWidth * 0.71,y: baseHeight + waveHeight * 0.64)
r2ControlPointView.center = CGPoint(x: maxRightX - (rightPartWidth * 0.44),y: baseHeight)
r3ControlPointView.center = CGPoint(x: maxRightX,y: baseHeight)
}

我试图用CABasicAnimation替换panGestureDidMove来设置起始位置的动画,如下面的代码:

let startValue = CGPointMake(70.0,50.0)
let endValue = CGPointMake(90.0,150.0)
CATransaction.setDisableActions(true) //Not necessary
view.layer.bounds.size.height = endValue
let positionAnimation = CABasicAnimation(keyPath:"bounds.size.height")
positionAnimation.fromValue = startValue
positionAnimation.toValue = endValue
positionAnimation.duration = 2.0
view.layer.addAnimation(positionAnimation,forKey: "bounds")

随着职位的变化,很多事情都会受到影响,我该怎样才能做到这一点?

如果您想要精确控制动画,可以使用CADisplayLink在屏幕像素刷新之前进行任何自定义布局或绘图.运行循环尝试每秒绘制60帧,因此考虑到这一点,您可以修改代码以模拟触摸事件.

您需要添加一些属性:

var displayLink:CADisplayLink? // let's us tap into the drawing run loop
var startTime:NSDate? // while let us keep track of how long we've been animating
var deltaX:CGFloat = 0.0 // how much we should update in the x direction between frames
var deltaY:CGFloat = 0.0 // same but in the y direction
var startValue = CGPointMake(70.0,50.0) // where we want our touch simulation to start
var currentPoint = CGPoint(x:0.0,y:0.0)
let endValue = CGPointMake(90.0,150.0) // where we want our touch simulation to end

然后,只要我们想要动画运行,我们就可以调用:

func animate()
    {
        let duration:CGFloat = 2.0
        self.currentPoint = self.startValue
        self.deltaX = (endValue.x - startValue.x) / (duration * 60.0) // 60 frames per second so getting the difference then dividing by the duration in seconds times 60
        self.deltaY = (endValue.y - startValue.y) / (duration * 60.0)
        self.startTime = NSDate()
        self.displayLink = CADisplayLink(target: self,selector: #selector(self.performAnimation))
        self.displayLink?.addToRunLoop(NSRunLoop.mainRunLoop(),forMode: NSDefaultRunLoopMode)
    }

这将设置显示链接并确定我的触摸模拟应在帧之间移动多少,并开始调用在每次绘制屏幕performAnimation之前调用的函数:

func performAnimation(){
        if self.startTime?.timeIntervalSinceNow > -2 {
            self.updateViewsFor(self.currentPoint,translation: CGPoint(x:self.currentPoint.x - self.startValue.x,y: self.currentPoint.y - self.startValue.y))
            self.currentPoint.x += self.deltaX
            self.currentPoint.y += self.deltaY
        }
        else
        {
            self.displayLink?.removeFromRunLoop(NSRunLoop.mainRunLoop(),forMode: NSDefaultRunLoopMode)
            self.currentPoint = self.startValue
        }
    }

在这里,我们检查是否在动画的持续时间内.然后调用updateViewsFor(点:CGPoint,翻译:CGPoint),这是你在手势目标中所拥有的,然后如果我们在其中,则更新我们的触摸模拟,否则我们只是重置我们的属性.

最后,

func updateViewsFor(point:CGPoint,translation:CGPoint)
    {
        let additionalHeight = max(translation.y,0)

        let waveHeight = min(additionalHeight * 0.6,maxWaveHeight)
        let baseHeight = minimalHeight + additionalHeight - waveHeight

        let locationX = point.x

        layoutControlPoints(baseHeight: baseHeight,locationX: locationX)
        updateShapeLayer()
    }

您还可以将panGestureDidMove更改为:

@objc func panGestureDidMove(gesture: UIPanGestureRecognizer) {
        if gesture.state == .Ended || gesture.state == .Failed || gesture.state == .Cancelled {

        } else {
            self.updateViewsFor(gesture.locationInView(gesture.view),translation: gesture.translationInView(view))
        }
    }

编辑

使用关键帧动画有一种更简单的方法.但我不确定它会为updateShapeLayer()设置动画.但是对于动画视图,我们可以编写如下函数:

func animate(fromPoint:CGPoint,toPoint:CGPoint,duration:NSTimeInterval)
    {            
        // Essentually simulates the beginning of a touch event at our start point and the touch hasn't moved so tranlation is zero
        self.updateViewsFor(fromPoint,translation: CGPointZero)

        // Create our keyframe animation using UIView animation blocks
        UIView.animateKeyframesWithDuration(duration,delay: 0.0,options: .CalculationModeLinear,animations: {

            // We really only have one keyframe which is the end. We want everything in between animated. 
            // So start time zero and relativeDuration 1.0 because we want it to be 100% of the animation
            UIView.addKeyframeWithRelativeStartTime(0.0,relativeDuration: 1.0,animations: {

                // we want our "touch" to move to the endValue and the translation will just be the difference between end point and start point in the x and y direction.
                self.updateViewsFor(toPoint,translation: CGPoint(x: toPoint.x - fromPoint.x,y: toPoint.y - fromPoint.y))
            })
            },completion: { _ in
                // do anything you need done after the animation
        })
    }

这会将视图移动到位,然后为视图结束的位置创建关键帧,并为其间的所有内容设置动画.我们可以称之为:

override func viewDidAppear(animated: Bool) {
        super.viewDidAppear(animated)
        self.animate(CGPointMake(70.0,50.0),toPoint: CGPointMake(90.0,150.0),duration: 2.0)
    }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读