mo.js 是一个致力于 Web 运动的 JavaScript 库。它提供声明式语法运动和用于动画的元素创建。尽管 mo.js 仍处于测试阶段,但已经提供了一系列令人惊叹的功能供您使用。它的作者 Oleg Solomoka(又名 @legomushroom)为该库提供了令人难以置信的演示和教程,您应该查看一下,但在本文中,我们将快速概述功能和教程以帮助您入门。
基本前提
mo.js 主要提供两种方法来制作运动的东西。您可以像其他库一样操作 DOM 或 SVG DOM 并移动它,或者您可以创建一个特殊的 mo.js 对象,它提供了一些非常独特的功能。两种工作方式都提供了一些基本功能,例如自定义路径缓动或时间轴。路径缓动和时间轴也提供了一些非常强大的工作工具,可以使您在工作时更容易调整它们。
形状
根据您正在制作的动画,mo.js 允许您制作的形状和其他对象可能会简化您的工作流程。mo.js 提供声明式语法,这使得在运行时创建东西变得非常容易。
以下是一个非常基本的示例
查看 CodePen 上 Sarah Drasner (@sdras) 的 mo.js 形状 1。
以下是一些您需要了解的基本内容
- 您可以使用的形状包括:
circle
、rect
、cross
、equal
、zigzag
和polygon
。(默认值为circle
) - 您可以定义填充、描边和描边宽度(默认值为填充且无描边或描边宽度。
Equal
和cross
没有填充空间,因此除非指定描边,否则不会显示。) - 您可以定义形状的半径,并使用附加的 radiusX 或 radiusY 在轴上调整它。(默认值为 50)
- 您可以通过
isShowStart
来指定是否显示形状,这是一个布尔值 - true 或 false。这样您就可以在不动画形状的情况下看到它。(默认值为 false) Polygons
、zigzag
和equal
允许您选择点数,以便您可以创建不同类型的形状(默认值为 3)- 所有形状都将使用绝对定位放置在屏幕中间,除非您指定 top、left 等。
以下是一些形状的示例
查看 CodePen 上 Sarah Drasner (@sdras) 的 mo.js 形状 2。
您可能注意到,如果您查看 DOM,这些形状是放置在 div 中用于定位的 SVG 形状。您还可以传递一个父级,例如 parent: '#id-to-be-placed-under'
,如果您想将形状放在 DOM 中的某个位置。您还可以传递任何 DOM 节点作为父级,因此 `parent: someEl`
也可以使用。在某个时候,您还可以选择使用 div 或 SVG,这将非常棒,因为如果您可以使用 SVG viewBox 来放置形状,它将使为移动设备创建缩放动画变得更加容易。
我们还可以创建自定义形状来制作动画,并将它们作为形状对象添加进去。
//custom shape
class OneNote extends mojs.CustomShape {
getShape () { return '<path d="M18.709
...
"/>'; }
}
mojs.addShape( 'oneNote', OneNote );
const note1 = new mojs.ShapeSwirl({
shape: 'oneNote',
...
});
形状运动
要在 mo.js 中使用形状创建动画,我们将传入一个对象,键值对表示我们想要从哪里开始到哪里结束。我们可以使用 scale 和 angle(在 CSS 中称为 rotate)之类的转换属性,以及不透明度,我们也可以像这里使用 fill 所示的那样对颜色进行插值。
scale: { 0 : 1.5 },
angle: { 0 : 180 },
fill: { '#721e5f' : '#a5efce' },
查看 CodePen 上 Sarah Drasner (@sdras) 的 mo.js 形状 3。
我们还可以指定一些其他参数
- duration
- delay
- repeat
- speed - 1 是默认速度,因此 0.5 将是半速,1.5 将是 1.5 倍速度
- isYoyo - 是否来回平滑过渡
- easing - 写成一个对象,如 ease.in、ease.out 或 ease.inout
- backwardEasing - 如果你想让 yoyo 的回摆不同,可以进行配置。这只在使用 isYoyo: true 时有效。如果你想让它回弹的方式与它前进的方式不同,你可以使用此方法指定。如果未指定,它将默认为 easing
- isSoftHide - 是否使用转换而不是显示来隐藏形状(布尔值,默认为 true)
随机
我们还可以通过编写以下字符串非常轻松地传递随机值 - property : 'rand(min, max)'
,例如 angle: ‘rand(0, 360)’
链接
如果我们想将两个动画链接到一个形状上,我们可以像这样在初始过渡上调用 .then()
const polygon = new mojs.Shape({
shape: 'polygon',
points: 5,
stroke: '#A8CABA',
scale: { 0 : 1.5 },
angle: { 0 : 180 },
fill: { '#721e5f' : '#a5efce' },
radius: 25,
duration: 1200,
easing: 'sin.out'
}).then ({
stroke: '#000',
angle: [-360],
scale: 0,
easing: 'sin.in'
});
查看 CodePen 上 Sarah Drasner (@sdras) 的 mo.js 形状 4。
旋转
像旋转和爆炸这样的东西是 mo.js 中非常有趣的部分,它们开箱即用就非常漂亮。旋转与普通形状对象非常相似,但运动几乎就像它的名字一样 - 形状在旋转。您有几个参数可以使用旋转,它们都基于旋转所使用的正弦曲线。
- swirlSize - 这是偏差 - 因此是它在水平方向上旋转的量
- swirlFrequency - 正弦曲线频率
- pathScale - 正弦曲线长度比例
- degreeShift - 这可以改变正弦曲线的方向,如果您想使其在 360 度上朝不同的方向移动,这尤其有用,特别适用于将旋转与爆炸一起使用
- direction - 正弦曲线的方向,-1 或 1(如果您想让它看起来有点随机,这对于将某个东西设置为另一个方向很有用)
- isSwirl - 形状是否应遵循正弦曲线路径(布尔值 - true 或 false)
这些可能有点难以阅读和理解,所以我做了一个演示,这样您就可以使用这些值来更好地理解它们
查看 CodePen 上 Sarah Drasner (@sdras) 的 Mo.js ShapeSwirl 选项。
此外,您可以使用一些基本配置(例如自定义形状或包含一些配置的对象)来重用几个不同的 SwirlShape
选项(或任何其他形状),使用 ES6 扩展运算符,如下所示,如果您有一些相似的对象,这真的很不错
const note_opts_two = {
shape: 'twoNote',
scale: { 5 : 20 },
y: { 20: -10 },
duration: 3000,
easing: 'sin.out'
};
const note1 = new mojs.ShapeSwirl({
...note_opts_two,
fill: { 'cyan' : color2 },
swirlSize: 15,
swirlFrequency: 20
}).then({
opacity: 0,
duration: 200,
easing: 'sin.in'
});
查看 CodePen 上 Sarah Drasner (@sdras) 的 小弹性收音机。
爆炸
爆炸开箱即用也非常漂亮。如果您使用默认配置,您会说这样
const burst = new mojs.Burst().play();
它将返回以下结果(点击 Rerun 按钮)
查看 CodePen 上 Sarah Drasner (@sdras) 的 最简单的 Mo.js 爆炸。
要配置爆炸,您有一些选项
- count - 爆炸中的子元素数量(默认值为 5)
- degree - 子元素来自中心的度数
- Radius - 子元素散布到的半径(radiusX 和 radiusY 也适用于此)
- isSoftHide - 是否使用转换而不是显示来隐藏子元素(布尔值,默认为 true) - 这适用于所有形状,但我再次提到它,因为它对于具有多个子元素的爆炸特别有用。
形状的所有规则也适用于爆炸效果,我们可以使用 `children` 将这些规则应用于节点本身作为单独的对象,就像这样。
const burst = new mojs.Burst({
radius: { 0: 100 },
count: 12,
children: {
shape: 'polygon',
...
}
});
查看 CodePen 上由 Sarah Drasner (@sdras) 创建的 玩转 mo.js 爆炸效果。
时间轴
在时间轴中,您可以 `add` 一堆之前声明为变量的对象或缓动,也可以 `append` 它们,并让它们按顺序排列。
const timeline = new mojs.Timeline({
.add( tween ) {}
.append( tween ) {}
});
- Add - 允许您将任何对象或形状添加到上述内容中,它们将同时触发(但您仍然可以使用延迟或交错来调整它们的计时)。
- Append - 添加对象,但按添加顺序交错它们。
在时间轴中,您可以执行一些值得注意的操作:您可以添加 `repeats`、`delays` 和 `speed`,就像对象本身一样,作为对象参数,就像这样。
new mojs.Timeline({
repeat: 3,
isYoyo: true
});
您还可以将时间轴嵌套在另一个时间轴中,甚至可以无限嵌套它们。
const subTimeline = new mojs.Timeline();
const master = new mojs.Timeline()
.add( subTimeline );
缓动
使用所有这些构造函数,我们甚至没有真正讨论过关于缓动(动画)已经存在的东西。所有相同的重复、持续时间和缓动也适用于缓动。要使用缓动,我们会根据进度更新样式或属性(您要更改的任何内容),这是一个简单的示例。
var thingtoselect = document.querySelector('#thingtoselect');
new mojs.Tween({
duration: 2000,
onUpdate: function (progress) {
square.style.transform = 'translateY(' + 200*progress + 'px)';
}
}).play();
在下面的 CodePen 中,我使用这种缓动来创建最左侧的锯齿形不断绘制自身的效果(使用 SVG 线条绘制技巧 和 `stroke-dashoffset`)。我也使用可用的路径缓动,这将在下一节中讨论。水箱中的水似乎通过更新 SVG 路径属性而移动。
new mojs.Tween({
repeat: 999,
duration: 2000,
isYoyo: true,
isShowEnd: false,
onUpdate: function (progress) {
var laser1EProgress = laser1E(progress);
for (var i = 0; i < allSideL.length; i++) {
allSideL[i].style.strokeDashoffset = 20*laser1EProgress + '%';
allSideL[i].style.opacity = Math.abs(0.8*laser1EProgress);
}
}
}).play();
查看 CodePen 上由 Sarah Drasner (@sdras) 创建的 带有 Mo.js 的射线枪。
缓动提供了非常丰富的回调,可以考虑微调,这些微调有时会带来巨大的变化。一些示例包括 onStart 与 onRepeatStart,onComplete 与 onRepeatComplete 以及 onPlaybackStart 与 onPlaybackPause。完整列表可在此处 文档中找到。
路径缓动
mo.js 的一个非常酷的功能是,除了其他 内置缓动值 之外,您还可以传入 SVG 路径作为缓动值。我在这篇文章中的几乎所有其他演示中都使用了此功能,但说实话,我无法像 Legomushroom 在 此页面上准备的精美教程 中那样充分展现路径缓动。我将简单解释基本前提以帮助您入门,并向您展示它是如何工作的,但真的,我强烈建议您阅读他的文章。
在我们深入了解所有路径缓动之前,必须明确一点:如果您想使用开箱即用的内容,基本功能会让您走得很远。内置缓动的语法如下所示。
easing: 'cubic.in'
掌握缓动技巧确实可以成为使动画栩栩如生的关键,因此能够使用自定义路径微调您的运动非常有用。如果您习惯于在 CSS 中进行动画制作,您可能会喜欢 Mo.js 贝塞尔缓动,它接受相同的曲线值(但没有 CSS 的三次贝塞尔曲线 的一些限制)。以下是一个此类缓动的示例。
easing: 'bezier( 0.910, 0.000, 0.110, 1.005 )'
如果您想要比贝塞尔缓动更精细的控制,那么路径缓动就很不错。您传入一个 SVG 路径,您的形状将在使用它时更新。让我们再次查看之前从射线枪中提取的示例。我们使用路径缓动在更新时插值这些值。
const laser1E = mojs.easing.path('M0,400S58,111.1,80.5,175.1s43,286.4,63,110.4,46.3-214.8,70.8-71.8S264.5,369,285,225.5s16.6-209.7,35.1-118.2S349.5,258.5,357,210,400,0,400,0');
new mojs.Tween({
repeat: 999,
duration: 2000,
isYoyo: true,
isShowEnd: false,
onUpdate: function (progress) {
var laser1EProgress = laser1E(progress);
for (var i = 0; i < allSideL.length; i++) {
allSideL[i].style.strokeDashoffset = 20*laser1EProgress + '%';
allSideL[i].style.opacity = Math.abs(0.8*laser1EProgress);
}
}
}).play();
要真正了解路径缓动如何影响动画的移动和行为,请查看工具部分中下面的示例 CodePen 演示。Mo.js 提供的曲线编辑器工具确实有助于可视化并立即了解缓动如何细化您的创作。
Mo.js 工具
关于 mo.js 最令人印象深刻的事情之一就是它的工具。要开始体验,请查看此 vimeo 视频。
我制作了一个非常简短的 CodePen 来展示播放器工具和曲线编辑器,以便您可以尝试使用它们。您可以随意将其派生或直接在 CodePen 中进行调整,尝试一下很有趣。曲线工具位于左侧,时间轴位于底部,有一个小箭头。
查看 CodePen 上由 Sarah Drasner (@sdras) 创建的 mo.js 形状 5 - 曲线编辑器。
最酷的部分是:Legomushroom 还没有完成。他现在正在为时间轴开发新的工具。查看此工具的出色设计 此处,并查看更广泛的标签 ‘求助’。如果您有兴趣为开源项目做出贡献,这是一个深入研究并帮助开发真正有用的工具的机会!
其他已完成的工具可以在它们自己的存储库中找到。
- 播放器:https://github.com/legomushroom/mojs-player
- 曲线编辑器:https://github.com/legomushroom/mojs-curve-editor
如果您有兴趣做出贡献或学习,还可以 加入 Slack 频道。
如果您是那种喜欢玩耍而不是阅读的人,这篇文章中的所有 CodePen 演示都可以在 此合集中找到。
当然,库中还有我在本文中没有介绍的内容。我介绍了一些我认为 mo.js 最有用的功能,但还有更多内容等着您去发现。查看 文档 以获取更多信息。特别感谢 Legomushroom 在文章发布前对本文进行校对。
感谢您介绍 JS。
这是一个很棒的介绍,Sarah!我看到很多 mo.js 演示都非常自然,我很好奇这到底有多少是库本身,多少是个人(我看到的大多数演示都是由 Oleg 创建的),多少是工具。那个曲线编辑器真是太棒了。
这篇文章非常有用。感谢管理员.. 我将为我的网站 http://www.webreciter.com 制作一些插件。
非常棒的文章 Sarah :),它与 GreenSock 相比如何?
我是 JS 动画库的新手。谢谢。