Koloda Tinder-Like Animation Version 2. Pixate 中的原

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

大约一个月前,我们告诉您 我们如何在 Swift 中开发类似 Tinder 的 Koloda 。动画在开发者和设计师社区中证明是成功的,所以我们决定继续玩它。

在我们推出第一个更简单的 Koloda 动画版本后, 我们的设计师 Dmitry Goncharov 坚持实施他的下一个想法。此外,我们的 iOS 开发人员和第一个 Koloda 动画的创建者 Eugene Andreyev 承诺进一步自定义帧的计算,以便任何开发人员都可以基于我们的开源项目制作自己独特的组件。

所以这是我们关于 Koloda 故事的第二章。这次我们将讨论设计和开发。同时你也可以在 Dribbble GitHub 上查看动画。

我们如何在 Pixate 中制作 Koloda 原型

德米特里·冈恰洛夫 (Dmitry Goncharov)

我受到类似 Tinder 的概念的启发,并决定详细阐述将 Koloda 变成不寻常的东西的最初想法。令人惊讶的是,几个小时后我想到了一个新概念。我的想法是摆脱一副纸牌并从背景中收集下一张纸牌。

我在 Photoshop 中设计了模型,并使用 Pixate 对其进行了原型制作。 Pixate 是类似于 InVision、Marvel、Origami、Form 等的设计工具。尽管在 Pixate 中制作原型比在 InVision 中花费更多时间,但结果看起来几乎就像一个真正的应用程序。我创建的原型完全按照我想要的方式再现了卡片的行为。

现在让我们谈谈这个过程。

Pixate 的主要工具集包括图层、动作套件和动画。在资产加载并位于画板上后,您可以开始在图层上工作,然后继续复制交互。

起初,我必须让卡片水平移动,一旦它们越过某条垂直线就飞离屏幕。我在一个简单的动画的帮助下做到了这一点,它可以在某些 if 条件下实现。我还让卡片在交互过程中改变了透明度并旋转了一点。

然后,我需要让一张新卡片看起来像是从背景中收集起来一样,所以必须拉伸和缩放它。我将原型的比例从 3.5 倍(当卡片仍在背景上时的尺寸)设置为 1 倍。

为了获得更好的效果,我添加了一些弹跳动画,仅此而已!原型已准备好进行开发。我想以我对 Pixate 的总体印象作为总结。

优点:

  • 在移动设备上预览
  • 简单的原型制作过程
  • 无需具备动画基础知识的具体知识
  • 原型看起来很像真正的 iOS 或 Android 应用程序
  • 方便的项目共享(导出到电脑、外部链接或二维码)

缺点:

  • 原型并不涵盖所有应用程序的功能,而是用于演示单独的功能和交互
  • 单个画板无法容纳原型的所有屏幕
  • 无法将原型导出为代码
  • 网络应用程序有点问题
  • 基本资产套件非常有限
  • 没有动画时间轴(以防您习惯 After Effects)

尽管有这些缺点,Pixate 是一个很棒的工具,它可以让设计师创建原生的可点击原型,重现导航模式和屏幕之间的交互,但最重要的是,它可以帮助整个团队理解项目开发的总体方向。 您可以观看 Jared Lodwick 的教程 以了解有关 Pixate 的更多信息。

现在你对 Koloda 的原型设计有了一些了解,是时候谈谈我们是如何开发第二版动画的了!

[科洛达动画第2版]

我们如何开发 Koloda v.2

尤金·安德烈耶夫

Koloda 动画第一版和第二版的主要区别在于卡片布局。新版本中的前卡位于屏幕中间,后卡在背景上拉伸。另外,后卡不响应前卡的移动,在前卡刷完后以弹跳效果到达。

此外,Koloda 的第二个版本更容易构建,因为 Dima 在 Pixate 中制作了它的原型。首先,Pixate 允许我观察原型上的所有交互。其次,我可以访问 Pixate studio 查看所有应用的转换及其顺序,然后只需将它们传递到代码中,而无需手动调整任何内容。

最后,Koloda 的第二个版本是旅行应用程序的一部分,这与第一个完全关于摇滚乐的版本不同。

[Koloda 动画版 1]

KolodaView v.2 的实现

为了实现 Dima 的动画,我不得不以不同的方式放置卡片,所以我将 上一篇 文章 (在 KolodaView 实现段落中)描述的魔术方法 frameForCardAtIndex 放在公共接口中。

KolodaView 继承者中,我覆盖了该方法并按以下顺序放置卡片:


 override func frameForCardAtIndex(index: UInt) -> CGRect {
   if index == 0 {

       let bottomOffset:CGFloat = defaultBottomOffset

       let topOffset:CGFloat = defaultTopOffset

       let xOffset:CGFloat = defaultHorizontalOffset

       let width = CGRectGetWidth(self.frame ) - 2 * defaultHorizontalOffset

       let height = width * defaultHeightRatio

       let yOffset:CGFloat = topOffset

       let frame = CGRect(x: xOffset, y: yOffset, width: width, height: height)

       return frame

   } else if index == 1 {

       let horizontalMargin = -self.bounds.width * backgroundCardHorizontalMarginMultiplier

       let width = self.bounds.width * backgroundCardScalePercent

       let height = width * defaultHeightRatio

       return CGRect(x: horizontalMargin, y: 0, width: width, height: height)

   }

   return CGRectZero

}

这里发生了什么?我们放置 frontCard KolodaView 的中间,并用等于 1.5 的 scalePercent 拉伸背景卡片。

背景卡片的弹跳动画

由于背景卡带有弹跳效果并在移动时改变其透明度,因此我创建了一个新的委托方法:


 override func frameForCardAtIndex(index: UInt) -> CGRect {
   if index == 0 {

       let bottomOffset:CGFloat = defaultBottomOffset

       let topOffset:CGFloat = defaultTopOffset

       let xOffset:CGFloat = defaultHorizontalOffset

       let width = CGRectGetWidth(self.frame ) - 2 * defaultHorizontalOffset

       let height = width * defaultHeightRatio

       let yOffset:CGFloat = topOffset

       let frame = CGRect(x: xOffset, y: yOffset, width: width, height: height)

       return frame

   } else if index == 1 {

       let horizontalMargin = -self.bounds.width * backgroundCardHorizontalMarginMultiplier

       let width = self.bounds.width * backgroundCardScalePercent

       let height = width * defaultHeightRatio

       return CGRect(x: horizontalMargin, y: 0, width: width, height: height)

   }

   return CGRectZero

}

在此方法中, 创建 POPAnimation 并将其传递给 Koloda。然后,Koloda 使用它在用户刷卡后动画帧变化。如果委托返回 nil ,则表示 Koloda 使用默认动画。

下面你可以在委托中看到这个方法的实现:


 override func frameForCardAtIndex(index: UInt) -> CGRect {
   if index == 0 {

       let bottomOffset:CGFloat = defaultBottomOffset

       let topOffset:CGFloat = defaultTopOffset

       let xOffset:CGFloat = defaultHorizontalOffset

       let width = CGRectGetWidth(self.frame ) - 2 * defaultHorizontalOffset

       let height = width * defaultHeightRatio

       let yOffset:CGFloat = topOffset

       let frame = CGRect(x: xOffset, y: yOffset, width: width, height: height)

       return frame

   } else if index == 1 {

       let horizontalMargin = -self.bounds.width * backgroundCardHorizontalMarginMultiplier

       let width = self.bounds.width * backgroundCardScalePercent

       let height = width * defaultHeightRatio

       return CGRect(x: horizontalMargin, y: 0, width: width, height: height)

   }

   return CGRectZero

}

如何防止背景卡移动?

我还在新版的Koloda中添加了一个delegate方法:


 override func frameForCardAtIndex(index: UInt) -> CGRect {
   if index == 0 {

       let bottomOffset:CGFloat = defaultBottomOffset

       let topOffset:CGFloat = defaultTopOffset

       let xOffset:CGFloat = defaultHorizontalOffset

       let width = CGRectGetWidth(self.frame ) - 2 * defaultHorizontalOffset

       let height = width * defaultHeightRatio

       let yOffset:CGFloat = topOffset

       let frame = CGRect(x: xOffset, y: yOffset, width: width, height: height)

       return frame

   } else if index == 1 {

       let horizontalMargin = -self.bounds.width * backgroundCardHorizontalMarginMultiplier

       let width = self.bounds.width * backgroundCardScalePercent

       let height = width * defaultHeightRatio

       return CGRect(x: horizontalMargin, y: 0, width: width, height: height)

   }

   return CGRectZero

}

如果返回 false 值,则表示交互动画已关闭,背景上的卡片不会与前面卡片的移动同时移动。

如果值为 false,则动画如下所示:

如果该值为 true,则如下所示:

希望您喜欢 Koloda 的第二个版本!检查一下:

另请阅读: