本文摘自使用JavaScript制作SVG动画 – 静华网-一个有气质的网站
更多信息请访问原文↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
在JavaScript中,使用CSS3或Web Animations API的浏览器本身可以实现的功能非常多。简单的动画和转换非常适合CSS3–而更复杂的动画需要使用JavaScript来完成。
Web Animation API的问题是浏览器支持和当前功能集。作为一个相当年轻的规格,这在未来几年会有所改进。
为了对抗这个功能和浏览器支持的不足,我们可以转向动画库,比如GreenSock(GSAP)。GSAP使我们能够创建复杂的动画和多个时间线,并能够动画几乎任何元素或属性/值对 – 所有这些都通过简单直观的语法来实现。
在本教程中,我们将使用GSAP库创建一些动画。我们将创建的主要和最复杂的动画将从白天到晚上过渡场景,我们将看到我们可以轻松地将多个转场链接在一起以创建复杂的动画。我们还将创建一些我们将不断运行的简单动画。
首先,我们需要分叉GreenSock Pen以试用其高级插件。对于本教程,我们将使用已经优化并粘贴到我们的HTML编辑器中的SVG。但是,如果您使用自己的SVG,则需要确保所有元素都具有唯一的ID。
GSAP提供两种时间线类型:TimelineLite和TimelineMax。TimeLineMax版本提供了其他功能,例如重复动画的能力,以及其他功能。我们的第一个时间表将是水,我们将无限次地来回重复。
1
2
3
4
|
var
animation_water
=
new
TimelineMax
(
{
repeat
:
-
1
,
yoyo
:
true
}
)
;
|
为了给水体加上动画,我们在SVG中有另一条路径,隐藏着’0’不透明度。我们将利用morphSVG插件将我们原来的水路改造成新的水路。我们将y轴上的水元素’12px’向下移动。该属性末尾的两个数字分别表示延迟时间和开始时间。
1
2
3
4
5
6
|
animation
_water
.
to
(
"#water"
,
2
,
{
y
:
12
,
morphSVG
:
"#water-2"
,
ease
:
Linear
.
easeNone
}
,
0
,
0
)
;
|
由于我们将重复使用许多属性和值,我们将为这些属性创建变量。
1
|
var
animation_ease
=
Linear
.
easeNone
;
|
GSAP图书馆使我们能够从任何给定的时间表中获取多个属性。我们可以将这些记录在控制台中,以确保一切正常,正如我们所期望的那样。
1
2
3
4
5
|
console
.
log
(
'animation_water duration: '
+
animation_water
.
duration
(
)
.
toFixed
(
2
)
)
;
|
对于我们希望单独进行动画制作的每个元素,我们需要不断创建新的时间线。我们还希望在控制台中记录时间线。
1
2
3
4
5
6
7
8
|
var
animation_cloud
=
new
TimelineMax
(
{
repeat
:
-
1
,
yoyo
:
true
}
)
;
console
.
log
(
'\n'
+
.
.
.
animation_cloud
.
duration
(
)
.
toFixed
(
2
)
+
' \n'
)
;
|
现在我们已准备好时间表,我们可以创建我们的云动画。采用新属性的动画片段可以处理多个使用逗号分隔的属性/值对。
我们的云动画只需要微妙,所以我们只需要少量更改这些值。
1
2
3
|
animation
_cloud
.
to
(
"#cloud"
,
3
,
{
x
:
-
2
,
y
:
1
,
scale
:
0.95
,
rotation
:
1
,
ease
:
animation_ease
}
,
0
,
0
)
;
|
接下来,我们将开始创建我们的日常动画。我们将为周期时间和一天创建一个变量。GSAP中的’yoyo’设置也使我们能够在重复之前延迟动画。
1
2
3
4
5
6
7
|
var
day_night_cycle_time
=
15
;
var
animation_delay
=
day_night_cycle_time
/
2
;
var
animation_toNight
=
new
TimelineMax
(
{
repeat
:
-
1
,
yoyo
:
true
,
repeatDelay
:
animation
_delay
}
)
;
|
在我们的SVG中,我们有一个由矩形组成的覆盖图层,覆盖整个图像,具有与我们夜间背景相同的背景渐变。覆盖层应用“乘法”混合模式以使整个图像变暗。我们的动画只是转换这个元素的不透明度。
1
2
3
4
5
6
7
8
|
animation
_toNight
.
to
(
'#nighttime-overlay'
,
day_night_cycle_time
,
{
opacity
:
1
,
ease
:
animation
_ease
}
,
0
,
0
)
;
|
GSAP在常用的“to”和“from”类型之上提供其他补间。为了让我们的渐变具有动画效果,我们需要的补间类型是’错开’到’补间’。我们还可以使用“循环”属性来将色轮旋转到我们的新值。
1
2
3
4
5
6
7
|
.
staggerTo
(
'#daytime-gradient stop'
,
day_night_cycle_time
,
{
cycle
:
{
stopColor
:
[
'#060414'
,
'#416584'
]
}
,
ease
:
animation_ease
,
}
,
0
,
0
)
|
我们可以不断为我们的’toNight’动画添加动画。这一次,我们将添加一个新的’来’补间,以设置我们的太阳。我们将显示时间设置为周期时间的一小部分,以便在月球前制作太阳动画。GSAP使我们能够设置几乎任何属性。我们将使用它来将’cx’和’cy’属性设置为右侧山丘下方的动画。
1
2
3
4
5
|
.
to
(
'#sun'
,
day_night_cycle_time
/
1.25
,
{
scale
:
0.9
,
attr
:
{
cx
:
"753"
,
cy
:
"697"
}
,
ease
:
animation_ease
}
,
0
,
0
)
|
我们将使用我们使用的相同技术将太阳变为视野外(请参阅上面的步骤11),以便将月球动画化为视图。当然,我们可以使用一个中间体来实现这一点,但为了创建人造弧,我们将分两部分来完成。在这两个部分中,我们也将为scale属性应用一个新值。
1
2
3
4
5
|
.
to
(
'#moon'
,
day_night_cycle_time
/
2
,
{
scale
:
0.9
,
attr
:
{
cx
:
"174.5"
,
cy
:
"202.5"
}
,
ease
:
animation_ease
}
,
0
,
0
)
|
月球动画的第二部分等待第一部分完成,然后开始。注意:这些动画代码中的这两部分月亮动画与我们正在使用的其他日常属性一起链接在一起。
1
2
3
4
5
6
7
8
|
animation
_toNight
.
.
.
.
to
(
'#moon'
,
day_night_cycle_time
/
2
,
{
scale
:
0.9
,
attr
:
{
cx
:
"410.5"
,
cy
:
"114.5"
}
,
ease
:
animation_ease
}
,
day_night_cycle_time
/
2
,
0
)
;
|
我们日常动画的唯一部分就是明星。我们将通过转换多个属性将星星变成视图。第一种方法是通过动画制作不透明来简单地将它们带入视野。
1
2
3
4
|
.
to
(
'#stars'
,
day_night_cycle_time
/
2
,
{
opacity
:
1
}
,
day_night_cycle_time
/
2
,
0
)
|
接下来,我们将使用补间的“from”来移动星星,并在它们生成视图时从负角度旋转它们。我们正在使用一些简单的数学来计算我们的动画时间和延迟,所有这些都基于我们的’day_night_cycle_time’变量。
1
2
3
4
5
|
.
from
(
"#stars"
,
day_night_cycle_time
-
(
day_night_cycle_time
/
4
)
,
{
y
:
150
,
rotation
:
-
15
,
ease
:
animation_ease
}
,
day_night_cycle_time
/
4
,
0
)
|
现在我们创建了我们的日常动画,我们可以创建另一个恒定的动画,以使我们的星星闪烁。我们将创建新的时间线,然后在控制台中记录时间线的持续时间。
1
2
3
4
|
var
animation_stars
=
new
TimelineMax
(
{
repeat
:
-
1
,
yoyo
:
true
}
)
;
|
现在我们为动画创建了时间轴,我们需要创建闪烁的动画。动画非常简单 – 我们所要做的就是减少不透明度值。由于’yoyo’属性,不透明度将会开启和关闭,这样会使星星看起来像是在闪烁。
1
2
3
4
5
|
animation
_stars
.
to
(
"#stars"
,
0.5
,
{
opacity
:
0.5
,
ease
:
animation_ease
}
,
0
,
0
)
;
|
在最后一步中,我们将目标定位为明星组,以应用我们闪烁的动画,但如果明星要一次闪烁一次,而不是同时闪烁一次,那么看起来会更好。我们通过分别针对每颗星星并应用不同的动画来实现这一点。
1
2
3
4
5
6
7
8
9
|
animation
_stars
…
.
to
(
"#star-two"
,
0.5
,
{
opacity
:
0.5
,
ease
:
animation_ease
}
,
1.25
,
0
)
.
to
(
"#star-three"
,
0.5
,
{
opacity
:
0.5
,
ease
:
animation_ease
}
,
.
75
,
0
)
…
;
|
而已!我们的日常骑车动画已经完成,看起来很棒,但我们不必停在那里。由于图像位于SVG中,因此我们可以轻松地为景观添加新元素。我们来添加一些雪。我们将使用两个单独的图层进行此操作。每个图层都有一个椭圆集合,足以覆盖景观,然后在上面重复相同的集合。
1
2
3
4
5
6
7
8
|
...
...
|
我们为我们的雪创建了两个单独的时间线,以便能够在不同的持续时间内制作动画。我们还会将他们的持续时间记录到控制台。
1
2
3
4
5
6
7
8
|
var
animation_snowTop
=
new
TimelineMax
(
{
repeat
:
-
1
,
repeatDelay
:
0
}
)
;
var
animation_snowBottom
=
new
TimelineMax
(
{
repeat
:
-
1
,
repeatDelay
:
0
}
)
;
|
为了激活我们的雪层,我们要沿着垂直轴移动这两层。通过不同的持续时间,我们将看到以不同速度移动的层的外观。动画通过沿着垂直轴移动椭圆集合直到第二个集合取代第一个集合。然后我们重复动画。
1
2
3
4
5
6
|
animation
_snow
.
to
(
"#snow-top-layer"
,
7
,
{
attr
:
{
transform
:
"translate(24 -108)"
}
,
ease
:
animation_ease
}
,
0
,
0
)
;
|