使用 CoreAnimation 或 OpenGL 弯曲/扭曲视图以实现轮播效果

发布于 2024-10-11 22:02:20 字数 284 浏览 7 评论 0原文

现在我正在用一系列视图填充 UIScrollView。需要扭曲视图以使 UIScrollView 看起来像旋转木马。换句话说,当用户滚动时,它需要像一个圆圈。我以前从未做过类似的事情,但我假设 CoreAnimation 是不可能的,并且需要使用 OpenGL。如果 CoreAnimation 或 Quartz 可以做到这一点,那么我真的只需要一个关于如何扭曲视图的示例,我可以自己解决其余的问题,但我不熟悉 OpenGL。

替代文本

Right now I'm populating a UIScrollView with a series of views. The views need to be warped to make the UIScrollView appear like a carousel. In other words when the user scrolls it needs to be like a circle. I've never done anything quite like this before, but I'm assuming CoreAnimation is out of the question and OpenGL needs to be used. If this is possible with CoreAnimation or Quartz then I really just need a sample on how to warp the views and I can figure the rest out myself but I'm not familiar with OpenGL.

alt text

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

妞丶爷亲个 2024-10-18 22:02:20

如果你想扭曲视图,你要么需要 OpenGL,要么你可以使用 Core Animation 的 CAShapLayer,它允许你指定一个可以包含这条曲线的贝塞尔路径。但请记住,您看到的这种弯曲可能只是一种视错觉(尽管在上面的图像中它看起来像一条实际的曲线)。如果您连续获得足够多的具有正确 y 轴旋转的矩形,我认为您可以通过直接核心动画获得您正在寻找的效果。我很确定这就是苹果几年前提供的核心动画演示中的实现方式。以下是该演示视频的屏幕截图:
Core Animation Layer Warping

我稍微搞乱了视图层的变换,然后想出了这个:

- (IBAction)sliderDidChange:(id)sender
{
  CGFloat value = [(UISlider*)sender value];
  CGFloat xOff = value - 0.5;

  CATransform3D trans = CATransform3DIdentity;
  trans.m34 = 1.0f / -1000.0f;

  trans = CATransform3DRotate(trans, degreesToRadians(xOff * -25.0f), 0.0f, 1.0f, 0.0f);
  trans = CATransform3DTranslate(trans, 0.0f, 0.0f, 900.0f * fabs(xOff));
  [[frameView layer] setTransform:trans];

  CGPoint center= [frameView center];
  [frameView setCenter:CGPointMake(1024.0 * value, center.y)];
}

我把它们放在一起演示项目,展示旋转如何响应滑块。它不使用滚动视图,因此您必须对其进行调整,但我认为您可以跟踪当前的滚动偏移并相应地应用变换。不确定它是否有帮助,但确实有帮助。

If you want to warp the views, you'll either need OpenGL or you could use Core Animation's CAShapLayer which allows you to specify a bezier path which can have this curve in it. But keep in mind that this curving you're seeing is likely just an optical illusion (though in your image above it looks like an actual curve). If you get enough rectangles with the correct y axis rotation in a row, I think you can come up with the effect you're looking for with straight Core Animation. I'm pretty sure that's how things are implemented in the Core Animation demos Apple provided a couple years ago. Here's a screenshot from the video from that presentation:
Core Animation Layer Warping

I messed around with the transform of a view's layer a little bit and came up with this:

- (IBAction)sliderDidChange:(id)sender
{
  CGFloat value = [(UISlider*)sender value];
  CGFloat xOff = value - 0.5;

  CATransform3D trans = CATransform3DIdentity;
  trans.m34 = 1.0f / -1000.0f;

  trans = CATransform3DRotate(trans, degreesToRadians(xOff * -25.0f), 0.0f, 1.0f, 0.0f);
  trans = CATransform3DTranslate(trans, 0.0f, 0.0f, 900.0f * fabs(xOff));
  [[frameView layer] setTransform:trans];

  CGPoint center= [frameView center];
  [frameView setCenter:CGPointMake(1024.0 * value, center.y)];
}

I threw together a demo project that shows how the rotation works in response to a slider. It doesn't use a scroll view so you would have to adapt it, but I think you can track the current scroll offset and apply the transform accordingly. Not sure if it will help but there it is.

傻比既视感 2024-10-18 22:02:20

根据我的经验,获得正确的值有点棘手。提供视图透视的方法是通过操纵它的图层变换。我使用以下方法来实现类似效果的转换:

-(CATransform3D)makeTransformForAngle:(CGFloat)angle from:(CATransform3D)start{

    CATransform3D transform = start;


    // the following two lines are the key to achieve the perspective effect
CATransform3D persp = CATransform3DIdentity;
    persp.m34 = 1.0 / -1000;

    transform = CATransform3DConcat(transform, persp);
        transform = CATransform3DRotate(transform,angle, 0.0, 1.0, 0.0);
    return transform;
}

这样做是为了创建“翻页”动画,因此您可能需要适应。要使用它,请执行以下操作:

flip_page.layer.transform = [self makeTransformForAngle:angle from:CATransform3DIdentity];

其中 Flip_page 是 UIView。干杯!

In my experience, it is a bit tricky to get the values right. The way to give a view perspective is by manipulating it's layer transform. I have used the following method to achieve the transfor for a similar effect:

-(CATransform3D)makeTransformForAngle:(CGFloat)angle from:(CATransform3D)start{

    CATransform3D transform = start;


    // the following two lines are the key to achieve the perspective effect
CATransform3D persp = CATransform3DIdentity;
    persp.m34 = 1.0 / -1000;

    transform = CATransform3DConcat(transform, persp);
        transform = CATransform3DRotate(transform,angle, 0.0, 1.0, 0.0);
    return transform;
}

This was done to create a "flip page" animation, so you may need to adapt. To use it, do the following:

flip_page.layer.transform = [self makeTransformForAngle:angle from:CATransform3DIdentity];

where flip_page is a UIView. Cheers!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文