iOS拖动UIView,布料效果

21

1
https://github.com/honcheng/PaperFold-for-iOS - Prashant Tukadiya
@BrightFuture 因为它在 dribble 上,我非常确定他是一位设计师,并且使用 Photoshop 设计了它。因此这不是一个屏幕截图。 - Paul Peelen
1
@MikeAlter 谢谢你的提示,但不幸的是那与附加的图片毫不相似。折叠视图并不难制作,我想学习的是如何制作布料效果。 - Paul Peelen
@BrightFuture 啊,没错。这个确实有一些好处。我会看看能否联系到设计师并问他。 - Paul Peelen
我现在没有时间尝试制作,但我会使用SceneKit。为什么?因为只需将backgroundColor设置为clear,就可以将SceneKit覆盖在UIKit上方。它可以使用UIView(或CALayer,我忘记了)作为几何体的纹理。然后创建一个具有大量细分和基于用户手指位置的几何变形的平面。仍然需要很多工作,但至少渲染方面已经为您处理好了。 - Kyle Howells
显示剩余5条评论
2个回答

9
简而言之:这真的非常困难。旧版Classics 应用程序使用一系列预先渲染的光滑纸张图像,在其视图内容的简单变换下实现了类似的效果,但正如您从这些屏幕截图中所看到的那样(以及下面的一张照片 - 请注意底部的文本仍在形成一条直线,因为它正在获得基本透视转换),该效果相当有限。

screenshot of Classics app showing page-turn effect

那个Dribbble设计中展示的效果要复杂得多,因为它实际上是对视图内容进行了缩紧变形,而不仅仅像Classics那样倾斜;目前我能想到在iOS上实现该效果的唯一方法是进入OpenGL并在那里使用网格扭曲内容。
更简单的选择是使用UIPageViewController,这将至少给你带来漂亮的iBooks风格翻页效果——虽然它不是织物,但比GL选项容易得多。

1
感谢您的答复。看起来我需要学习如何在OpenGL中实现它。我猜这将是我长期的个人项目 =) - Paul Peelen
5
如果你想开始学习,GPU Pro 2这本书有一章使用OpenGL ES来复制实际的翻页效果。该书的源代码可以在这里找到:http://www.crcpress.com/product/isbn/9781568817187,我可以看到你可能能够修改页面网格以使其变皱而不是翻转。您的UIView可以渲染为纹理以映射到该网格上。 - Brad Larson
1
你也可以尝试使用CoreImage。将视图渲染成UIImage,然后在图像上应用效果。通过正确的扭曲效果组合,你可能能够复制所需的效果。 - Fogmeister
另一个查找OpenGL水波纹示例的地方是苹果公司的GLCameraRipple项目。它在实时摄像机视图中创建了一个水波纹,当你在屏幕上拖动手指时产生效果。https://developer.apple.com/library/content/samplecode/GLCameraRipple/Introduction/Intro.html - charmingToad

2
这已经有一个开源的重新实现了。

这篇博客文章: Mesh Transforms 讲述了私有的 CAMeshTransform。它不仅将CALayer视为简单的四边形,还允许将CALayer转换为相互连接的网格面。这个类是苹果实现页面翻页和iBooks翻页效果的方式。

然而,该API无法很好地容忍格式错误的输入,苹果也将其保留为私有API。

如果您继续阅读该博客文章,您会看到在提到它是私有API后的下一节内容。

在CAMeshTransform的精神下,我创建了一个BCMeshTransform,几乎复制了原始类的所有功能。
...
没有直接、公共访问Core Animation渲染服务器,我被迫使用OpenGL来实现。这并不是一个完美的解决方案,因为它引入了一些原始类没有的缺点,但似乎是目前唯一可用的选项。

实际上,他将内容视图转换为OpenGL纹理,然后显示出来。这使他可以随心所欲地进行操作。包括像这样...
“我鼓励你去看一下我为BCMeshTransformView制作的演示应用程序。它包含了一些如何使用网格变换来丰富交互的想法,例如我的简单但功能强大的 那个著名的Dribbble。”
什么是著名的Dribbble?就是这个:

这是示例的样子:

开源项目:

BCMeshTransformView:https://github.com/Ciechan/BCMeshTransformView
窗帘效果的示例实现:BCCurtainDemoViewController.m


它通过设置一些光照和透视来配置 BCMeshTransformView
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L59
self.transformView.diffuseLightFactor = 0.5;

CATransform3D perspective = CATransform3DIdentity;
perspective.m34 = -1.0/2000.0;
self.transformView.supplementaryTransform = perspective;

然后使用UIPanGestureRecognizer来跟踪触摸,并在用户手指移动时使用此方法构建一个新的网格变换。
// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCCurtainDemoViewController.m#L91
self.transformView.meshTransform = [BCMutableMeshTransform curtainMeshTransformAtPoint:CGPointMake(point.x + self.surplus, point.y) boundsSize:self.transformView.bounds.size];

// From: https://github.com/Ciechan/BCMeshTransformView/blob/master/Demo/BCMeshTransformViewDemo/BCMeshTransform%2BDemoTransforms.m#L14
+ (instancetype)curtainMeshTransformAtPoint:(CGPoint)point boundsSize:(CGSize)boundsSize
{
    const float Frills = 3;

    point.x = MIN(point.x, boundsSize.width);

    BCMutableMeshTransform *transform = [BCMutableMeshTransform identityMeshTransformWithNumberOfRows:20 numberOfColumns:50];

    CGPoint np = CGPointMake(point.x/boundsSize.width, point.y/boundsSize.height);

    [transform mapVerticesUsingBlock:^BCMeshVertex(BCMeshVertex vertex, NSUInteger vertexIndex) {
        float dy = vertex.to.y - np.y;
        float bend = 0.25f * (1.0f - expf(-dy * dy * 10.0f));

        float x = vertex.to.x;

        vertex.to.z = 0.1 + 0.1f * sin(-1.4f * cos(x * x * Frills * 2.0 * M_PI)) * (1.0 - np.x);
        vertex.to.x = (vertex.to.x) * np.x + vertex.to.x * bend * (1.0 - np.x);

        return vertex;
    }];

    return transform;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接