在上一篇文章中 ,我介绍了将Bootstrap轮播转换为具有随机初始图像的全屏轮播的过程。 在本文中,我将以此为基础,并借助流行的JavaScript库GSAP (GreenSock动画平台)的帮助,对Bootstrap轮播动画进行动画处理。
在继续进行之前,让我们看一下要构建的内容 。
制作轮播
确保在页面中包含Bootstrap和jQuery(Bootstrap的JavaScript组件需要它),例如,来自CDN:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Using GSAP for Animating Bootstrap Carousels</title>
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
</head>
<body>
...
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
</body>
</html>
轮播的基本结构如下所示:
<div id="mycarousel" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#mycarousel" data-slide-to="0" class="active"></li>
<li data-target="#mycarousel" data-slide-to="1"></li>
</ol>
<div class="carousel-inner">
<!-- first slide -->
<div class="carousel-item first active" id="1">
<!-- content here -->
</div>
<!-- second slide -->
<div class="carousel-item second" id="2">
<!-- content here -->
</div>
</div><!-- /carousel-inner -->
</div>
如您所见,它包含两个幻灯片。 第一滑动件具有一类的first
和的ID 1
,而第二个具有一类的second
和的ID 2
。
关于他们的风格:
- 我们将其高度设置为等于视口高度
- 我们给他们提供不同的背景颜色。
关联的CSS规则:
.item {
height: 100vh;
}
.first {
background: #D98F4F; /*orange*/
}
.second {
background: #2c9cae; /*lightblue*/
}
这应该足以为我们提供工作中的传送带。
制作第一张幻灯片
接下来,我们利用Bootstrap的帮助器类(例如Grid类 )来设置幻灯片的内容。
第一张幻灯片的标记如下:
<div class="carousel-item first active" id="1">
<div class="carousel-caption">
<div class="container">
<div class="row justify-content-md-center">
<div class="col">
<h2 class="title">
<!-- content here -->
</h2>
<p class="desc">
<!-- content here -->
</p>
<ul class="list">
<!-- list items here -->
</ul>
</div>
<div class="col">
<div class="pc-wrapper">
<img class="pc" src="IMG_PATH" alt="" width="" height="">
<div class="price">
<!-- content here -->
</div><!-- /price -->
</div><!-- /pc-wrapper -->
<img class="keyboard" src="IMG_PATH" alt="" width="" height="">
<button type="button" class="btn btn-danger btn-lg">
<!-- content here -->
</button>
</div>
</div><!-- /row -->
</div><!-- /container -->
</div><!-- /carousel-caption -->
</div><!-- /carousel-item -->
如果您遵循此步骤,请务必使用明智的方法替换IMG_PATH
。
结果如下所示:
制作第二张幻灯片
同样,这是第二张幻灯片的标记:
<div class="carousel-item second" id="2">
<div class="carousel-caption">
<div class="container">
<h2 class="title">
<span>
<!-- content here -->
</span>
</h2>
<div class="row justify-content-md-center">
<div class="col cms-wrapper">
<div class="cms">
<div class="front">
<!-- content here -->
</div>
<div class="back">
<img class="img-fluid" src="IMG_PATH" alt="">
</div><!-- /back -->
</div><!-- /cms -->
<p class="info">
<!-- content here -->
</p>
</div><!-- /cms-wrapper -->
<!-- two more columns here -->
</div><!-- /row -->
<div class="source">
<!-- content here -->
</div><!-- /source -->
</div><!-- /container -->
</div><!-- /carousel-caption -->
</div><!-- /carousel-item -->
及其可视化:
注意:为简单起见,我们不会广泛介绍幻灯片内部的样式。 我们将仅提及对动画很重要的样式。
初始化轮播
接下来,我们通过将interval:false
传递给配置对象来初始化轮播并禁用默认的自动播放:
var $carousel = $("#mycarousel");
$carousel.carousel({
interval: false
});
添加键盘导航
默认情况下,Bootstrap轮播不符合辅助功能标准。 不过,在我们的情况下,让我们通过添加键盘导航使轮播更易于访问。
这是必需的代码:
$(document).keyup(function(e) {
// right arrow
if(e.which === 39) {
$carousel.carousel("next");
// left arrow
} else if(e.which === 37) {
$carousel.carousel("prev");
}
});
到目前为止,我们已经构建了一个支持键盘导航的基本轮播。
引导传送带动画:第一个动画
在这一点上,让我们通过添加一些动画来使轮播更具吸引力。 为此,我们将利用GSAP的优势,GSAP是目前功能最强大的JavaScript动画库之一。 如果您想对GreenSock进行全面介绍,请查看GreenSock for Beginners:Web动画教程(第1部分) 。
GSAP入门
要将GSAP纳入我们的项目,我们必须访问其站点,然后从该站点 单击页面右上角显示的下载按钮。 这将打开一个模式对话框,其中包含指向CDN上项目的链接。
如果然后选择“ 定制”单选按钮,则可以选择要使用的库的各个部分。 但是,对于我们的项目,我们将使事情变得简单,仅包括其完整的强大版本。
记住,我们必须在项目中添加jQuery,因为Bootstrap的轮播依赖于它。 但是,请记住,GSAP是纯JavaScript库,因此不需要它。
动画引导带轮播:第一张幻灯片
默认情况下,我们希望隐藏幻灯片的内容:
.carousel-caption {
opacity: 0;
}
仅当页面加载时,我们才显示第一张幻灯片的内容并为其设置动画。 为此,我们利用TimelineLite这个动画工具来帮助我们构建补间序列。
因此,一旦所有页面资产准备就绪,就会执行firstTimeline
函数:
// this variable stores the first timeline
var firstTl;
$(window).on("load", function() {
firstTl = firstTimeline();
});
此函数返回一个时间轴,该时间轴确定第一张幻灯片的动画:
function firstTimeline() {
var tl = new TimelineLite();
tl
.to(".first .carousel-caption", 0.1, {opacity: 1})
.from(".first .pc", 1, { y: -300, opacity: 0, ease: Bounce.easeOut})
.from(".first .keyboard", 1, { y: 300, opacity: 0, ease: Bounce.easeOut}, "-=1")
.staggerFrom(".first .list li", 0.75, {opacity: 0, cycle: {x: [-200, 200]}, ease: Power2.easeOut}, 0.15, "-=0.5")
.from(".first .desc", 0.7, {x: 500, opacity: 0, ease: Power4.easeOut}, "-=0.5")
.from(".first .title", 0.7, {x: -500, opacity: 0, ease: Power2.easeOut}, "-=0.7")
.from(".first .price", 0.7, {scale: 0.01, ease: Power4.easeOut})
.from(".first button", 0.7, { y: -700, autoAlpha: 0, ease: Bounce.easeOut}, "-=0.3");
return tl;
}
更具体地说,在上面的函数中,我们执行以下操作:
- 创建一个TimelineLite
- 使用其to , from和staggerFrom方法将补间添加到时间线
- 返回时间轴。
让我们记下传递给to
和from
方法的参数:
- 我们要设置动画的DOM元素。
- 动画的持续时间(以秒为单位)。
- 一个对象,其中包含应补间的属性及其各自的(开始或结束)值。 此外,该对象还可以具有一些其他特殊属性,例如定义缓动函数的
ease
属性。 - 补间在时间轴中的位置。 换句话说, 应在何时执行此补间 。 例如,我们要同时运行
.first .pc
和.first .keyboard
元素的动画。 为此,我们将.first .keyboard
元素的position
参数的值设置为"-=1"
。 此值内的数字“ 1”与.first .pc
元素的动画持续时间匹配。
在类似的to
和from
方法,我们通过相同的参数到staggerFrom
方法。 唯一的区别是,我们定义了一个附加参数(第四个参数),该参数指定每个补间的开始时间。 在我们的示例中,此值设置为0.15
。 也就是说,目标元素不会同时出现,但是它们的动画之间会有很小的间隙。 将该值更改为较大的值(例如5),以查看效果的明显差异。
显然,了解上述动画的工作原理的最佳方法是阅读文档。 另外,使用浏览器的开发人员工具查看GSAP应用于目标元素的样式。
因此,让我们简要地仔细看一下分配给按钮的动画。
最初,按钮具有autoAlpha: 0
和y: -700
。 这意味着它在视觉上是隐藏的( opacity: 0
, visibility: hidden
),并且位于其原始位置上方700像素处( transform: matrix(1, 0, 0, 1, 0, -700)
)。
然后,当动画播放时,它变为可见( opacity: 1
, visibility: inherit
)并返回其默认位置( transform: matrix(1, 0, 0, 1, 0, 0)
)。
最后,动画在时间轴结束之前的0.3秒开始。
提示:使用TimelineLite的duration
方法检索其持续时间。 这里的关键是要了解如何计算该值。
到目前为止做得好! 第一张幻灯片的动画已经准备好! 您可以在此Codepen演示中实时看到它们: 使用GSAP对Bootstrap Carousels进行动画处理(第1部分) 。
使用Bootstrap的轮播事件
当我们离开第一张幻灯片并移至第二张幻灯片时(反之亦然),我们的幻灯片内容应被隐藏。 轮播完成幻灯片切换后,它应该立即出现。 要实现此行为,我们利用以下优势:
- Bootstrap提供的
slide.bs.carousel
和slid.bs.carousel
事件。 - GSAP的TweenLite动画工具可帮助我们构建单个补间。 请注意,在上一节中,我们使用TimelineLite创建了一系列补间。
这是必要的代码:
var $carouselCaption = $(".carousel-caption");
$carousel.on("slide.bs.carousel", function() {
TweenLite.to($carouselCaption, 0.1, {opacity: 0});
});
$carousel.on("slid.bs.carousel", function () {
TweenLite.to($carouselCaption, 0.1, {opacity: 1});
});
如前所述,页面加载时,第一张幻灯片的动画运行。 但是什么时候应该再次运行? 另外,第二张幻灯片及其动画呢? 为了回答所有这些问题,让我们在slid.bs.carousel
事件的回调中添加几行代码:
// these variables store the timelines
var firstTl, secondTl;
$carousel.on("slid.bs.carousel", function (e) {
TweenLite.to($carouselCaption, 0.1, {opacity: 1});
var slideId = e.relatedTarget.id;
if(slideId === "1") {
firstTl.restart();
} else if(slideId === "2") {
secondTl = secondTimeline();
}
});
上面的代码执行以下操作:
- 它检查我们的幻灯片的
id
。 - 如果
id
等于1
,则第一张幻灯片已加载,因此我们必须重播此幻灯片的动画。 请记住,我们已经为这些动画创建了时间线(在firstTimeline
函数中),因此我们可以使用其restart
方法再次播放它。 - 如果
id
等于2
,则第二张幻灯片已加载,因此执行了secondTimeline
函数(请参阅下一节)。
动画引导带轮播:第二张幻灯片
secondTimeline
函数返回一个时间线,该时间线确定第二张幻灯片的动画:
function secondTimeline() {
var tl = new TimelineLite({onComplete: allDone});
tl
.from(".second .title", 0.5, { y: -400, opacity: 0, ease: Sine.easeInOut})
.staggerFrom(".second .cms-wrapper", 0.5, {scale: 0, rotation: 180, ease: Power2.easeInOut, onComplete: completeFunc}, 1.2);
return tl;
}
更具体地说,在上面的函数中,我们执行以下操作:
- 创建一个TimelineLite
- 使用其
from
和staggerFrom
方法将补间添加到时间线 - 返回时间轴。
尽管此时间轴看起来像我们先前为第一张幻灯片创建的时间轴,但这里有些事情我们之前从未见过。
首先,查看传递给staggerFrom
方法的对象。 它包含一个名为onComplete
的特殊属性。 该属性包含一个函数(即completeFunc()
),当每个目标元素的动画结束时会触发该函数。
让我解释。
默认情况下,仅显示具有.second .front
(即数字)类的元素。
.second .back
(即CMS徽标)和.second .info
(即CMS名称)元素被隐藏。
以下是相应的CSS规则:
.second .back {
display: none;
transform: scale(0);
}
.second .info {
opacity: 0;
transform: translateY(40px);
}
当为每个.second .cms-wrapper
元素运行completeFunc
函数时,我们将设置补间,这些补间会影响子元素的可见性。 具体来说,我们隐藏.second .front
元素,然后(在0.3秒延迟后)显示.second .back
和.second .info
元素。
在下面您可以看到相关的JS代码:
function completeFunc() {
var $this = $(this.target),
$info = $this.find(".info"),
$front = $this.find(".front"),
$back = $this.find(".back");
TweenLite.to($front, 0.3, {display: "none", scale: 0});
TweenLite.to($back, 0.3, {display: "block", scale: 1, delay: 0.3});
TweenLite.to($info, 0.3, {opacity: 1, y: 0, delay: 0.3});
}
此时间轴中的第二件事是在所有动画结束时运行的回调。 我们通过将带有onComplete
属性(其值为allDone
函数)的配置对象传递给构造函数来指定此方法。
时间轴完成后,将触发此函数并显示最初不可见的.second .source
元素( opacity: 0
, visibility: hidden
)。
这是allDone
函数:
function allDone() {
TweenLite.to(".second .source", 0.3, {autoAlpha: 1, delay: 1});
}
现在,让我们检查一下轮播的当前状态: 使用GSAP对Bootstrap轮播进行动画处理(第2部分) 。
动画看起来不错,但是关于第二张幻灯片仍然存在一个小问题。 更具体地说,我们第一次访问第二张幻灯片时,动画按预期工作。 但是,在任何其他情况下(对其进行测试),结果都不理想,因为CMS徽标不会生成动画。
要解决此问题,我们必须重新启动相应的时间轴(请记住,我们对第一张幻灯片进行了相同的操作),并清除了completeFunc
和allDone
函数中定义的补间(内联样式)。 最后,当第一个时间轴处于活动状态时,我们暂停第二个时间轴。 考虑到这一点,我们再次像下面这样更新slid.bs.carousel
事件的回调:
var counter = 0,
firstTl,
secondTl;
$carousel.on("slid.bs.carousel", function (e) {
TweenLite.to($carouselCaption, 0.1, {opacity: 1});
var slideId = e.relatedTarget.id;
if(slideId === "1") {
firstTl.restart();
secondTl.pause();
} else if(slideId === "2") {
if(counter === 0) {
secondTl = secondTimeline();
} else {
TweenLite.set([".second .front", ".second .back", ".second .info", ".second .source"], {clearProps:"all"});
secondTl.restart();
}
counter++;
}
});
因此,最后,这是我们轮播的新版本: 使用GSAP对Bootstrap轮播进行动画处理(第3部分) 。
禁用JavaScript时自定义轮播
转盘快要准备好了。 在结束包装之前,让我们自定义禁用JavaScript时的外观。 在这种情况下,幻灯片必须位于彼此之间,并且自定义消息应鼓励用户启用JavaScript。
这是所需的可视化效果:
实现此行为的一种方法是使用<noscript>
标记。 这个选项很棒,但是它向我们的HTML中添加了一些额外的代码,因此让我们尝试一些不同的东西。
默认情况下,我们将no-js
类添加到<html>
标记中。 当浏览器解析页面时,如果此浏览器中启用了JavaScript,则该类将被删除。
因此,首先,在HTML中添加以下代码:
<p class="msg">
It seems you have JavaScript disabled. The carousel doesn’t work well without JavaScript. Please enable it!
</p>
然后,在CSS中执行此操作(主要是重置规则):
.msg {
display: none;
position: fixed;
top: 5px;
left: 50%;
transform: translateX(-50%);
padding: 7px;
border: 5px solid #fff000;
text-align: center;
color: #fff;
background: rgba(0, 0, 0, .85);
z-index: 999;
}
.no-js .carousel-inner > .item {
display: block;
}
.no-js .carousel-caption,
.no-js .second .info,
.no-js .second .source {
opacity: 1;
}
.no-js .second .info {
transform: none;
}
.no-js .second .source {
visibility: visible;
}
.no-js .carousel-indicators {
display: none;
}
.no-js .msg {
display: block;
}
最后,在页面的<head>
标记中,插入以下代码段:
<script>
document.documentElement.className = "";
</script>
请记住,我们将此代码放在<head>
标记内,因为我们希望在浏览器开始绘制元素之前执行该代码。 这对于防止DOM闪烁很重要。
这是我们轮播的最终版本:
请参阅CodePen上带有 SitePoint( @SitePoint )的GSAP动画的笔式引导轮播 。
结论
在本文中,我们经历了使用GSAP对Bootstrap轮播进行动画处理的过程。 您可以在此Codepen集合中找到本文的所有演示。 毫无疑问,我们涵盖了很多领域,但希望您喜欢我们构建的内容并了解GSAP的功能! 补间快乐!
有什么问题吗 注释? 您在项目中使用GSAP吗? 我希望在下面的评论中收到您的来信。
本文由Joan Yinn和Yaphi Berhanu进行了同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!
如果您掌握了Bootstrap的基础知识,但又想知道如何将Bootstrap技能提高到一个新的水平,请查看我们的使用Bootstrap 4建立您的第一个网站课程,以快速,有趣地介绍Bootstrap的功能。
From: https://www.sitepoint.com/animating-bootstrap-carousels-gsap/