如何在 Swift 中为绘图设置动画,同时更改 UIImageView 的比例? [英] How to animate drawing in Swift, but also change a UIImageView's scale?

查看:13
本文介绍了如何在 Swift 中为绘图设置动画,同时更改 UIImageView 的比例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想制作一个绘图序列的动画.我的代码在 UIImageView.image 中绘制了一个螺旋线.该序列改变了图像内容,但也改变了周围 UIImageView 的 scale.代码参数化为螺旋的转数:

I'd like to animate a drawing sequence. My code draws a spiral into a UIImageView.image. The sequence changes the image contents, but also changes the scale of the surrounding UIImageView. The code is parameterized for the number of revolutions of the spiral:

func drawSpiral(rotations:Double) {
let scale = scaleFactor(rotations)   // do some math to figure the best scale

UIGraphicsBeginImageContextWithOptions(mainImageView.bounds.size, false, 0.0)
let context = UIGraphicsGetCurrentContext()!
context.scaleBy(x: scale, y: scale)      // some animation prohibits changes!
// ...  drawing happens here
myUIImageView.image = UIGraphicsGetImageFromCurrentImageContext()
}

例如,我想在 1.0 秒的持续时间内以 20 个增量从 drawSpir​​al(2.0)drawSpir​​al(2.75) 制作动画.

For example, I'd like to animate from drawSpiral(2.0) to drawSpiral(2.75) in 20 increments, over a duration of 1.0 seconds.

我可以设置 UIView.annimate(withDuration...) 以使用连续的中间值调用我的方法吗?如何?有更好的动画方法吗?

Can I setup UIView.annimate(withDuration...) to call my method with successive intermediate values? How? Is there a better animation approach?

推荐答案

我可以设置 UIView.annimate(withDuration...) 用连续的中间值调用我的方法

Can I setup UIView.annimate(withDuration...) to call my method with successive intermediate values

动画只是一连串定时的中间值被扔到某物上.要求将它们扔到您的代码中是完全合理的,这样您就可以对它们做任何您喜欢的事情.方法如下.

Animation is merely a succession of timed intermediate values being thrown at something. It is perfectly reasonable to ask that they be thrown at your code so that you can do whatever you like with them. Here's how.

你需要一个特殊的层:

class MyLayer : CALayer {
    @objc var spirality : CGFloat = 0
    override class func needsDisplay(forKey key: String) -> Bool {
        if key == #keyPath(spirality) {
            return true
        }
        return super.needsDisplay(forKey:key)
    }
    override func draw(in con: CGContext) {
        print(self.spirality) // in real life, this is our signal to draw!
    }
}

该层实际上必须在界面中,尽管用户可能无法看到:

The layer must actually be in the interface, though it can be impossible for the user to see:

let lay = MyLayer()
lay.frame = CGRect(x: 0, y: 0, width: 1, height: 1)
self.view.layer.addSublayer(lay)

接下来,我们可以初始化层的spirality:

Subsequently, we can initialize the spirality of the layer:

lay.spirality = 2.0
lay.setNeedsDisplay() // prints: 2.0

现在,当我们想要动画"spirality 时,我们会这样做:

Now when we want to "animate" the spirality, this is what we do:

let ba = CABasicAnimation(keyPath:#keyPath(MyLayer.spirality))
ba.fromValue = lay.spirality
ba.toValue = 2.75
ba.duration = 1
lay.add(ba, forKey:nil)
CATransaction.setDisableActions(true)
lay.spirality = 2.75

控制台显示一连串中间值在 1 秒内到达!

The console shows the arrival of a succession of intermediate values over the course of 1 second!

2.03143266495317
2.04482554644346
2.05783333256841
2.0708108600229
2.08361491002142
2.0966724678874
2.10976020619273
2.12260236591101
2.13551922515035
2.14842618256807
2.16123360767961
2.17421661689878
2.18713565543294
2.200748950243
2.21360073238611
2.2268518730998
2.23987507075071
2.25273013859987
2.26560932397842
2.27846492826939
2.29135236144066
2.30436328798532
2.31764804571867
2.33049770444632
2.34330793470144
2.35606706887484
2.36881992220879
2.38163591921329
2.39440815150738
2.40716737508774
2.42003352940083
2.43287514150143
2.44590276479721
2.45875595510006
2.47169743478298
2.48451870679855
2.49806520342827
2.51120449602604
2.52407149970531
2.53691896796227
2.54965999722481
2.56257836520672
2.57552136480808
2.58910304307938
2.60209316015244
2.6151298135519
2.62802086770535
2.64094598591328
2.6540260463953
2.6669240295887
2.6798157542944
2.69264766573906
2.70616912841797
2.71896715462208
2.73285858333111
2.74564798176289
2.75
2.75
2.75

这些正是将在动画属性中抛出的数字,例如当您将视图的框架原点 x2 更改为 2.75 在 1 秒持续时间的动画中.但是现在数字以数字的形式出现在您面前,因此您现在可以用这一系列数字做任何您喜欢的事情.如果您想在每个新值到达时调用您的方法,请继续.

Those are exactly the numbers that would be thrown at an animatable property, such as when you change a view's frame origin x from 2 to 2.75 in a 1-second duration animation. But now the numbers are coming to you as numbers, and so you can now do anything you like with that series of numbers. If you want to call your method with each new value as it arrives, go right ahead.

这篇关于如何在 Swift 中为绘图设置动画,同时更改 UIImageView 的比例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆