CoreAnimation 层并非都以相同的速度移动:我错过了什么?
我有一个带有 CALayers 的应用程序,可以从屏幕的一侧移动到另一侧。我试图获得正确的时间,以便它们都花费相同的时间从第一侧传递到我决定的任意分隔符(靠近另一侧),然后继续运行以从屏幕上消失。
这是我的意思的一个例子:
两个盒子应该以相同的速度移动(动画具有线性Timing),所以当小方框碰到分隔符时,两者之间的小间隙应该是相同的。
不过,我更愿意看到这样的:
用文字表达,似乎我的大盒子移动得比小盒子。
这是我的代码的相关部分。我决定每秒像素的速度,然后考虑到必须移动的像素框数量来设置动画的持续时间。
const CGRect viewBounds = CGRectMake(0,0, 500, 400);
const CGFloat distanceToCross = viewBounds.size.width - delimiterX;
const CFTimeInterval timeToCross = 5;
const CGFloat pixelsPerSecond = distanceToCross / timeToCross;
const CGFloat y = /* y coordinate of the box */;
CALayer* box = [CALayer layer];
// the layer should lie outside the viewport at first
box.frame = CGRectMake(viewBounds.size.width, y, /* size here */);
box.anchorPoint = CGPointMake(0, 0.5);
// snip
[CATransaction begin];
CATransaction.animationTimingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
CATransaction.animationDuration = (viewBounds.size.width + box.frame.size.width) / pixelsPerSecond;
// and the layer should cross the viewport to outside of it, too
box.position = CGPointMake(-box.frame.size.width, y);
[CATransaction commit];
这在我的图形示例中没有显示,但是相同大小的盒子都以相同的速度运行,所以显然我在时间计算上做错了。我缺少什么?
I have an app with CALayers
that move from one side of the screen to the other. I am trying to get the timing right so that they all take the same time to pass from the first side to an arbitrary delimiter I've decided on (near the other side), then continue their run to disappear from the screen.
Here's an example of what I mean:
Both boxes should move at the same speed (the animation has linear timing), so when the small box hits the delimiter, the small gap between the two should be the same.
However, I rather see this:
Expressed with words, it seems that my large box is moving faster than the small box.
Here's the relevant part of my code. I decide a speed in pixels per second, then set the duration of the animation considering the number of pixels boxes have to travel.
const CGRect viewBounds = CGRectMake(0,0, 500, 400);
const CGFloat distanceToCross = viewBounds.size.width - delimiterX;
const CFTimeInterval timeToCross = 5;
const CGFloat pixelsPerSecond = distanceToCross / timeToCross;
const CGFloat y = /* y coordinate of the box */;
CALayer* box = [CALayer layer];
// the layer should lie outside the viewport at first
box.frame = CGRectMake(viewBounds.size.width, y, /* size here */);
box.anchorPoint = CGPointMake(0, 0.5);
// snip
[CATransaction begin];
CATransaction.animationTimingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
CATransaction.animationDuration = (viewBounds.size.width + box.frame.size.width) / pixelsPerSecond;
// and the layer should cross the viewport to outside of it, too
box.position = CGPointMake(-box.frame.size.width, y);
[CATransaction commit];
This is not shown in my graphical example, but boxes of the same size all go at the same speed, so obviously I'm doing something wrong with my time calculation. What am I missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
CALayer.position
默认情况下表示框的中心点。因此,每个框的结束帧实际上超出了您想要的点,并且超出的量取决于框的大小。这将导致您的计算失败,因为您的持续时间是基于错误的距离。我很惊讶你没有注意到你的盒子在移动时稍微向下漂移,因为y
坐标同时用于frame.origin.y
和position .y 也是如此。
一个简单的修复方法是取框架的中点。您可以通过执行类似的操作来做到这一点
或者要使其在面对
anchorPoint
更改时具有弹性,您可以使用类似的操作CALayer.position
, by default, indicates the center point of the box. As such, your ending frame for each box is actually past the point you want, and the amount it goes over is based on the size of the box. This is going to throw off your calculation since your duration is based on the wrong distance. I'm surprised you haven't noticed your boxes drifting slightly downwards as they move, since they
coordinate is used for bothframe.origin.y
andposition.y
as well.A simple fix is to take the midpoint of the frame. You can do this by doing something like
Or to make it resilient in the face of
anchorPoint
changes, you could use something like