本文译自:《 Comprehensive guide to prototyping VR in Framer 》
原文作者:Sophie Rahier
翻译:Jun
原文地址:https://blog.framer.com/comprehensive-guide-to-prototyping-vr-in-framer-29b7dd1bdd2a
最近我和 Ben 的主要工作就是使用 Framer 和 Sketch 设计 VR 原型,在这篇文章里我们总结一下这个项目的经验。
在此之前我们对 Framer 知之甚少,关于 VR 原型的经验也几乎没有。所以这篇文章的目标读者也是想要尝试这个却无从下手的人。使用 Framer 设计 VR 原型的优点是可以快速迭代,而且不需要任何 3D 渲染器。下文所写的这些方法都是十分简单且灵活的,希望它能够在 Framer 或 VR 原型设计之路上助你一臂之力。
我们的目的是在 VR 环境中创建一个类似于鼠标悬浮响应的动画,请使用电脑访问 https://framer.cloud/quZbq 来体验我们的原型。
开始
由于将设计元素或图片转为 VR 场景时会有一定的扭曲,所以找一个合适的网格系统作为参考很有必要。KickPush 曾发布过一个 Sketch 的栅格模板( https://dribbble.com/shots/3190567-VR-design-template-by-Kickpush ),并说明了如何使用它来预览 Sketch 设计在 GoPro VR 播放器中的样子。我们建议在制作 VR 原型之前先使用这个工具对你的复杂界面进行一个测试。
如果你有一个 oculus 在手上,那么使用用 GoPro VR 播放器来预览很简单,就像是安装一个显示器那么简单。
规划交互
我们发现想要制作出最符合心中预期的交互原型的方法就是把你所想到的每一个交互效果用最简单的话写下来,在心里过一下整个交互流程,写下每一处的动画和它们的触发动作。
比如:
-
鼠标悬浮在方块上方时,方块变大。
-
离开方块,方块变成原来大小。
这对于 Framer 学习很有帮助,Charlie Deets 曾在他的一篇关于工作流程的文章里写过详细的过程,如果你刚开始学习 Framer 推荐阅读一下。
( 地址:https://medium.com/facebook-design/framer-sketch-an-intentional-workflow-f91ee2ee1cc1 )
VR组件
Framer VR 组件是设计制作 VR 交互原型的关键。
下载成功之后,你需要将它放在正确的 Framer 项目 modules 文件夹下。

接下来就是引用这个组件,并使用它创建一个类似于立方体的环境。
# 引用 VR 模块
{VRComponent, VRLayer} = require "VRComponent"
# 创建一个新的 VR 组件,并对该环境贴图
vr = new VRComponent
front: "images/front.png"
left: "images/left.png"
right: "images/right.png"
back: "images/back.png"
top: "images/top.png"
bottom: "images/bottom.png"
你可以将图片放在此在项目的 images 文件夹下,用来替换每一面的背景(默认是纯色)。
也许你注意到了,GoPro 视图采用了圆柱形的贴图,而这里却是立方体贴图。没关系,我们使用这个转换器把圆柱形贴图照片转换成立方体贴图。
http://gonchar.me/panorama
设置好 VRComponent 之后,为了更好地定位和移动场景,我们还需要设置一个光标。写它的样式你可以随意写,下面这个可以供参考:
#光标
reticle = new VRLayer
width: 20
height: 20
borderRadius: 100
backgroundColor: "transparent"
borderWidth: 4
reticle.center()
这些设置完毕,你就可以像在普通的 Framer 原型中一样去添加图层和交互,只不过所有图层都必须是 VR 图层,还要通过 VRLayer 去展现它们。
#Create a new VR layer
layerA = new VRLayer
# Project layerA as VR layer
vr.projectLayer(layerA)
下一步,悬浮动效。这需要理解方位角和天顶角的概念。
理解方位角和天顶角
这个 VR 组件是基于球坐标系创建的,而球坐标系最主要的两个概念是方位角和天顶角,它们的具体意义是:
-
方位角(heading):具有一个从 0 到 360 度的极角。
-
高低角(elevation):具有一个从 -90 到 90 度的天顶角。
当方位角从 0 到 180 变化时你会观察到物体在球面右侧,180 到 360 度时在球面左侧。类似地,当高低角是正数时物体上移,负数时下移。
最开始时用户的视角点所处的方位角和高低角都是 0 度,你可以调整这两个角度来调整图层位置。
#设置图层属性
layerA = new VRLayer
elevation: 5
heading: 0
上面的示例代码中,图层水平居中且向上移动了 5 度,注意坐标系始终与图层中心相关。
你可以用下面这两行代码输出图层的方位角和高度角。
print layerA.heading
print layerA.elevation
这对于我们制作悬浮效果是很有用的,因为它的位置检测是依赖于方位角和高低角的。在进行 VR 光标悬浮动画设计时,与普通原型不同的是我们要关注的不是光标是否在某个图层上,而是光标或者你的视角所处的方位角和高低角是否在这个位置。
对于光标悬浮的动画,我们定义图层所处的一块位置区域,当某个方位角和高低角处于这个位置时就触发一个动作。
该区域的面积取决于图层的面积。在这里,我们设置在方位角和高低角两个方向都是 6 度的范围,它覆盖了 100×100 的图层 A 。因为图层 A 有一个 5 度的高低角,所以它的上下边界是 2 到 8 度。

图层A的动画区域,蓝色部分是方位角和高低角的范围
那么,这就是说当图层A的方位发生变化并落在此区域内时,我们要给图层 A 设置动画,一旦离开此区域则恢复原样。
所以我们应该监听图层的方位改变事件:
#监听方位变化事件
vr.on Events.OrientationDidChange, (data) ->
heading = data.heading
elevation = data.elevation
tilt = data.tilt
当该事件发生时,我们要实时判断图层 A 是否处于刚才划定的范围内,如果是的话就要给它添加动画了。
#监听方位变化
vr.on Events.OrientationDidChange, (data) ->
heading = data.heading
elevation = data.elevation
tilt = data.tilt
#定义图层 A 执行动画的区域
if 2 < elevation < 8 && 0 < heading < 3 || 2 < elevation < 8 && 357 < heading < 360
layerA.animate
scale: 1.3
options:
time: 0.63
curve: Spring(damping: 0.55)
#离开此区域则恢复原样
else
layerA.animate
scale: 1
options:
time: 0.63
curve: Spring(damping: 0.55)
这里因为方位角横跨了 0 度两侧的范围,所以我们要分开来写,如果没有横跨两侧则不需要。
代码初学者请注意,在 if/else 判断语句中,&& 和 || 分别表示逻辑与和逻辑或。逻辑与表明当它两侧的条件都满足时才会执行动画,逻辑或表示当它满足其中一侧的条件时就会触发动画。
添加音效
添加音效需要一个比较小的音频和音频组件。像我们之前处理 VR 组件一样,这一次我们需要把音频组件的模块放置在模块文件夹中,同时创建一个音频文件夹用来放置你所有的音频文件。
接着像调用 VR 组件一样调用音频组件:
# 引用音频模块
{AudioPlayer} = require "audio"
接着设置需要播放的音频文件:
#设置需要播放的文件
soundA = new AudioPlayer
audio: "audio/soundA.mp3"
这样就可以通过一个事件来触发音频播放了。
# 点击时播放音频
layerA.onClick ->
soundA.player.play()
在本例中,音频也是这个交互动画的一部分。
希望看着这篇文章之后对于 VR 原型设计感兴趣的朋友可以开始尝试,我们也会继续分享相关资源,不管是 VR 还是 Framer 相关的。
感谢阅读。
