Spark AR 是 Facebook 免费创作 AR 作品的平台,使用户能够为 Facebook 和 Instagram 创建交互式增强现实体验,超过 40 万名创作者,190个国家/地区,使用 Spark AR 来创作自己的AR作品
由于该软件无需任何编码知识即可使用,因此任何人现在都可以在 AR 世界中几乎没有经验地制作下一个疯狂式传播的 Instagram AR 特效,引领世界潮流。
专门的 AR 滤镜设计师单价甚至可达到 1000 美元到 3 万美元不等。
录音机的扬声器动画
我们正在创建的第二个动画将应用于录音机的扬声器,以给他们播放音频的外观。
访问扬声器
与基础对象一样,我们需要访问脚本中的扬声器,这次我们需要场景面板中的speaker_left_jnt 和 speaker_right_jnt 对象。
在基对象下面的一行中添加访问 speaker 对象的代码:
脚本代码
Scene.root.findFirst('base_jnt') // Existing code
.then(function(base) { // Existing code
Scene.root.findFirst('speaker_left_jnt')
.then(function(speakerLeft) {
Scene.root.findFirst('speaker_left_jnt')
.then(function(speakerLeft) {
上面的代码,至少需要 3 帧来执行(由于 Promise 链),看起来相当混乱。我们可以通过 Promise.all API 调用大块的 find 请求来优化它,而不是一个一个地调用。这样的优化只需要 1 帧来执行:
Promise.all([
Scene.root.findFirst('base_jnt'),
Scene.root.findFirst('speaker_left_jnt'),
Scene.root.findFirst('speaker_right_jnt')
])
.then(function(objects) {
const base = objects[0];
const speakerLeft = objects[1];
const speakerRight = objects[2];
在访问场景中的三个对象时,我们调用 Scene.root 三次,这是一个提高脚本性能的机会。如果我们存储 Scene.root 在一个变量中,我们只需要调用它一次,并且可以任意使用这个变量。
添加以下代码将 root 存储在变量中,并更新访问对象的行:
const sceneRoot = Scene.root;
// Existing code updated
Promise.all([
sceneRoot.findFirst('base_jnt'),
sceneRoot.findFirst('speaker_left_jnt'),
sceneRoot.findFirst('speaker_right_jnt')
])
.then(function(objects) {
const base = objects[0];
const speakerLeft = objects[1];
const speakerRight = objects[2];
sceneRoot 变量现在已经取代了单独的 Scene.root 属性调用。
完整脚本代码
const Animation = require('Animation');
const Scene = require('Scene');
const sceneRoot = Scene.root;
// Existing code updated
Promise.all([
sceneRoot.findFirst('base_jnt'),
sceneRoot.findFirst('speaker_left_jnt'),
sceneRoot.findFirst('speaker_right_jnt')
])
.then(function(objects) {
const base = objects[0];
const speakerLeft = objects[1];
const speakerRight = objects[2];
const baseDriverParameters = {
durationMilliseconds: 400,
loopCount: Infinity,
mirror: true
};
const baseDriver = Animation.timeDriver(baseDriverParameters);
baseDriver.start();
const baseSampler = Animation.samplers.easeInQuint(0.9,1);
const baseAnimation = Animation.animate(baseDriver,baseSampler);
const baseTransform = base.transform;
baseTransform.scaleX = baseAnimation;
baseTransform.scaleY = baseAnimation;
baseTransform.scaleZ = baseAnimation;
});
创建扬声器动画
现在我们可以为扬声器创建驱动器、采样器和动画,就像我们为基对象所做的那样。
对于驱动器,我们将使用与基本对象驱动器类似的参数,但设置的持续时间为 0.2 秒。
脚本代码
const speakerDriverParameters = {
durationMilliseconds: 200,
loopCount: Infinity,
mirror: true
};
const speakerDriver = Animation.timeDriver(speakerDriverParameters);
speakerDriver.start();
对于采样器,我们将使用不同的缓动函数和值。
脚本代码
const speakerSampler = Animation.samplers.easeOutElastic(0.7,0.85);
这些值比我们用于基础对象的值要小,因为扬声器本身是更小的物体。一个 ease out 函数意味着动画将快速开始但较慢结束。
随着驱动器和采样器的创建,我们现在可以创建动画。
脚本代码
const speakerAnimation = Animation.animate(speakerDriver,speakerSampler);
完整代码如下
const Animation = require('Animation');
const Scene = require('Scene');
const sceneRoot = Scene.root;
// Existing code updated
Promise.all([
sceneRoot.findFirst('base_jnt'),
sceneRoot.findFirst('speaker_left_jnt'),
sceneRoot.findFirst('speaker_right_jnt')
])
.then(function(objects) {
const base = objects[0];
const speakerLeft = objects[1];
const speakerRight = objects[2];
const baseDriverParameters = {
durationMilliseconds: 400,
loopCount: Infinity,
mirror: true
};
const baseDriver = Animation.timeDriver(baseDriverParameters);
baseDriver.start();
const baseSampler = Animation.samplers.easeInQuint(0.9,1);
const baseAnimation = Animation.animate(baseDriver,baseSampler);
const baseTransform = base.transform;
baseTransform.scaleX = baseAnimation;
baseTransform.scaleY = baseAnimation;
baseTransform.scaleZ = baseAnimation;
const speakerDriverParameters = {
durationMilliseconds: 200,
loopCount: Infinity,
mirror: true
};
const speakerDriver = Animation.timeDriver(speakerDriverParameters);
speakerDriver.start();
const speakerSampler = Animation.samplers.easeOutElastic(0.7,0.85);
const speakerAnimation = Animation.animate(speakerDriver,speakerSampler);
});
应用动画到扬声器
我们现在可以应用新的动画到两个扬声器对象,动画将用于改变他们的缩放比例。
脚本代码
const speakerLeftTransform = speakerLeft.transform;
speakerLeftTransform.scaleX = speakerAnimation;
speakerLeftTransform.scaleY = speakerAnimation;
speakerLeftTransform.scaleZ = speakerAnimation;
const speakerRightTransform = speakerRight.transform;
speakerRightTransform.scaleX = speakerAnimation;
speakerRightTransform.scaleY = speakerAnimation;
speakerRightTransform.scaleZ = speakerAnimation;
在使用缩放方法将 speakerAnimation 信号绑定到扬声器之前,要访问扬声器的变换。这意味着两个扬声器将以相同的方式进行动画。
脚本代码
const Animation = require('Animation');
const Scene = require('Scene');
const sceneRoot = Scene.root;
// Existing code updated
Promise.all([
sceneRoot.findFirst('base_jnt'),
sceneRoot.findFirst('speaker_left_jnt'),
sceneRoot.findFirst('speaker_right_jnt')
])
.then(function(objects) {
const base = objects[0];
const speakerLeft = objects[1];
const speakerRight = objects[2];
const baseDriverParameters = {
durationMilliseconds: 400,
loopCount: Infinity,
mirror: true
};
const baseDriver = Animation.timeDriver(baseDriverParameters);
baseDriver.start();
const baseSampler = Animation.samplers.easeInQuint(0.9,1);
const baseAnimation = Animation.animate(baseDriver,baseSampler);
const baseTransform = base.transform;
baseTransform.scaleX = baseAnimation;
baseTransform.scaleY = baseAnimation;
baseTransform.scaleZ = baseAnimation;
const speakerDriverParameters = {
durationMilliseconds: 200,
loopCount: Infinity,
mirror: true
};
const speakerDriver = Animation.timeDriver(speakerDriverParameters);
speakerDriver.start();
const speakerSampler = Animation.samplers.easeOutElastic(0.7,0.85);
const speakerAnimation = Animation.animate(speakerDriver,speakerSampler);
const speakerLeftTransform = speakerLeft.transform;
speakerLeftTransform.scaleX = speakerAnimation;
speakerLeftTransform.scaleY = speakerAnimation;
speakerLeftTransform.scaleZ = speakerAnimation;
const speakerRightTransform = speakerRight.transform;
speakerRightTransform.scaleX = speakerAnimation;
speakerRightTransform.scaleY = speakerAnimation;
speakerRightTransform.scaleZ = speakerAnimation;
});
保存你的脚本并返回 Spark AR Studio
现在,扬声器将在场景中动画起来。