iPhone 动画基于输入值(触摸)而不是时间
对于完全适合动画组方法的动画效果,如 布拉德·拉尔森的回答在这里,我需要动画根据输入进行。特别是触摸和检测到的触摸的位置。处理 TouchMoved: 并为每次触摸设置元素的位置很容易,但它不像核心动画方法那样平滑。
想象一下有凹槽的轨道上的弹珠。我想将弹珠以任意速度向一个方向或另一个方向推到任意位置。动画必须做类似的事情,沿着路径移动视觉元素以响应触摸。 CAKeyframeAnimation 具有精确的路径位,但似乎总是希望将帧到帧的转换基于经过的时间,而不是基于任何其他因素,并且是在一个方向上。
1 月 31 日更新 - 感谢迄今为止所有的回复,但没有一个能真正解决问题。我有一个圆形菜单,可以拖动它来选择一个选项。所有这些都需要一起移动,我已经通过使用应用了旋转变换的视图来解决这个问题,并将逆旋转变换应用于其子视图,以便图标都以适当的摩天轮方向旋转。当图标沿着稍微卵形的路径进行动画处理时,它确实看起来更好......大理石描述是为了弄清楚我想要做什么。也许更好地想象磁铁的方向是排斥所有在凹槽中行进的磁铁——移动一个磁铁,它的邻居也会移动,但不一定沿着被拖动的磁铁随着路径弯曲移动的方向。
现在的问题是遵循一个用一个圆创建的简单路径,但我真的很想知道如何沿着任意路径对对象进行动画处理,位置纯粹通过触摸控制,不涉及速度或方向的计算。
For an animation effect perfectly suited to an animation group approach as shown in Brad Larson's answer here, I need the animation to proceed according to inputs. Specifically touch and position of detected touches. It is easy to handle touchesMoved: and to set the position of the elements for every touch but it just isn't smooth like the core animation approach.
Imagine a marble in a grooved track. I want to push the marble along to any position at any speed in one direction or the other. The animation has to do something like that, moving a visual element along a path in response to touches. CAKeyframeAnimation has the path bit exactly but seems to always want to base the transition from frame to frame on time elapsed, not on any other factor, and in one direction.
31 January update - Thanks all for the responses so far however none is really solving the problem. I have a circular menu that is dragged to select an option. All of it needs to move together and I have worked around it by using an view that has a rotational transform applied and the inverse rotational transform applied to its subviews so the icons all rotate with appropriate ferris wheel orientation. It really looks better when the icons are animated along a slightly ovoid path though... the marble description is an attempt to make clear what I'm trying to do. Better perhaps to imagine magnets oriented to repel all travelling in a groove - move one and its neighbours move too but not necessarily in the direction that the dragged magnet moves as the path curves.
Right now the problem is one of following a simple path created with one circle but I'd really like to know how to animate objects along an arbitrary path, position controlled purely by touch with no calculations involving velocity or direction.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您可以使用层次结构性质图层树中的时间线以实现您正在寻找的内容。实现
CAMediaTiming
< 的对象/a>,其中包括 CAAnimation 和 CALayer,从其父级继承时间空间,它们可以修改该时间空间(通过缩放、移位和重复)并将其传播到其子级。通过将图层的speed
属性设置为 0.0 并手动调整timeOffset
属性,您可以将该图层(及其所有子图层)与通常的时间概念分离。在您的情况下,您要做的是为所有菜单项定义动画,以从时间 t0 开始沿您所需的
CGPath
动画显示它们的位置到t1,在每个动画上使用适当的timeOffset
,以保持项目适当的间距。请注意,动画上的beginTime
为 0.0 通常被解释为从动画添加到其图层的时间开始,因此如果您想要 t0 为 0.0,您可能需要将其设置为一个很小的 epsilon > 0.0。然后,您可以将父图层(仅包含这些菜单项)上的
speed
属性设置为 0.0,并将其timeOffset
更新为 t 之间的值0 和 t1 响应您的触摸事件。这种方法有两个潜在的警告。因为您已经接管了该图层子树上的时间性质,所以您可能无法同时为其他属性设置动画。此外,如果您想要快速滑动的滑行行为,您可能需要自行设置时间动画。
You may be able to use the hierarchical nature of timelines in layer trees to achieve what you’re looking for. Objects implementing
CAMediaTiming
, which include bothCAAnimation
andCALayer
, inherit a timespace from their parent, which they can modify (via scaling, shifting and repeating) and propagate to their children. By setting thespeed
property of a layer to 0.0 and adjusting thetimeOffset
property manually, you can decouple that layer (and all of its sublayers) from the usual notion of time.What you’d do in your case is define the animations for all your menu items to animate their position along your desired
CGPath
from time t0 to t1, with the appropriatetimeOffset
on each animation to keep your items appropriately spaced. Note that abeginTime
of 0.0 on an animation is usually interpreted as starting from the time the animation was added to its layer, so if you want t0 to be 0.0, you'll probably have to set it to a tiny epsilon > 0.0.You’d then set the
speed
property to 0.0 on a parent layer (containing only these menu items) and update itstimeOffset
to values between t0 and t1 in response to your touch events.This approach has two potential caveats. Because you’ve taken over the nature of time on this layer subtree, you probably won’t be able to animate other properties at the same time. Additionally, if you want coasting behavior for a fast flick, you’ll probably need to animate time forward on your own.
速度=距离/时间。您可以尝试根据移动的触摸和时间给予延迟。您可以计算touchesBegan 和touchesEnded 方法之间的时间。
velocity = distance/time. You can try by giving delay according to touches moved and time. You can calculate time between touchesBegan and touchesEnded methods.
如果您的目标是 iOS 4.0 或更高版本,则可以使用 新的基于块的类方法,用于启动对 查看 对象。因此,您可以通过触摸事件对视图上的属性发起可动画的更改:
注意这可以很容易地更改视图上的另一个属性,例如其位置。您可以通过这种方式为视图上的以下属性设置动画:
如果您的目标是早期版本的 iOS,则需要使用 UIView beginAnimations 和 commitAnimations 方法来创建动画块:
这个东西效果非常好,一旦你开始使用它,你就必须小心不要上瘾。 ;)
评论更新:
您可以将弹珠的位置绑定到触摸事件的位置。一旦你得到 touchesEnded 事件,然后您可以使用动画块为弹珠的位置设置动画。
If you are targeting iOS 4.0 or greater then you can use the new block based class methods to start animatable changes to view objects. So from your touch event you can initiate an animatable change to properties on the view:
N.B. This could just as easily be a change to another property on the view, like its location. You can animate the following properties on the view this way:
If you are targetting earlier versions of iOS you will need to use UIView beginAnimations and commitAnimations methods to create an animation block:
This stuff works really well and once you start using it, you will have to be careful you don't get addicted. ;)
Update for comment:
You can bind the position of the marble to the location of the touch event. Once you get the touchesEnded event you can then animate the location of the marble using an animation block.
我不完全确定我完全理解你想要做什么,但是......为什么不直接在用户手指所在的地方绘制弹珠呢?不需要动画。
如果您想让弹珠在用户放手后保持移动,您需要保持动量的概念并使用它来动画弹珠减速。您可以使用 CoreAnimation 或计时器。
I'm not entirely certain I understand exactly what you want to do but... Why not just draw the marble wherever the user's finger is? No animation required.
If you want to keep the marble moving after the user lets go, you need to maintain a concept of momentum and use that to animate the marble slowing down. You could use either CoreAnimation for that or a timer.
我会在移动的触摸中进行速度计算,并将其添加到一个局部变量中,块可以通过计时器进行变异。
换句话说,在移动的触摸中,考虑到先前速度的方向进行速度计算。在接触结束后,发射一个方块,将“弹珠”平移,并根据您的需要降低速度。如果用户再次移动弹珠,请修改局部变量,这将反过来加快弹珠的动画速度或减慢速度/根据触摸方向改变方向。
I would make a velocity calculation in touches moved, and add it to a local variable that a block can mutate via a timer.
in other words, in touches moved make a velocity calculation bearing in mind the direction of a previous velocity. In touches ended, fire a block that translates the 'marble' decaying the velocity as you disire. If the user moves the marble again, modify the local variable, this will in turn speed up the animation of the marble or slow it down/change direction depending on on the direction of the touch.