今天咱们想向您展现如何使用CSS Masks建立一个有趣的过渡效果。 与剪切相似,遮罩是定义可见性和与元素复合的另外一种方式。 在下面的教程中,咱们将向您展现如何在简单轮播图中为过渡效果应用新属性。 咱们将使用steps()计时功能动画,并在图像上移动遮罩PNG以实现有趣的过渡效果。html
注意:请记住,这种效果还处于实验阶段,只有现代浏览器支持(Chrome,Safari和Opera)。web
使用所选图像来遮盖元素的一部分的方法spring
W3C候选人推荐浏览器
支持如下版本:bash
桌面应用app
移动端应用框架
能够在caniuse.com上查看详细的支持状况dom
请记住,Firefox只有部分支持(它只支持内联SVG遮罩元素)因此咱们会有一个回退版本。 但愿CSS Masks能尽快获得全部现代浏览器的支持。 请注意,咱们正在添加Modernizr以检查是否支持。ide
让咱们一块儿愉快的开始吧!
在本教程中,咱们将介绍第一个示例(演示1)。
为了使遮罩过渡效果起做用,咱们须要一个图像,用于隐藏/显示基础图像的某些部分。 该遮罩图像将是一个PNG,上面有透明部分。 这个PNG将是一个雪碧图,它看起来以下:
黑色部分将显示当前图像,但白色部分(其实是透明的)将是咱们图像的遮罩部分,将显示第二个图像。
为了建立雪碧图,咱们将使用此视频。 咱们将其导入Adobe After Effects以减小视频的时间,删除白色部分并将其导出为PNG序列。
要将持续时间缩短到1.4秒(咱们但愿转换的时间),咱们将使用时间拉伸效果(Time stretch effect)。
要删除白色部分,咱们将使用Keying -> extract并将白点设置为0.在下面的屏幕截图中,蓝色部分是咱们合成的背景,即视频的透明部分。
最后,咱们能够将合成的视频保存为PNG序列,而后使用Photoshop或CSS sprite生成单个图像:
这是一个雪碧图,具备很是连贯的外观效果。 咱们将为另外一种效果建立另外一个“反向”雪碧图。 您将在演示文件的img文件夹中找到全部不一样的雪碧图。
如今,咱们已经建立了遮罩图像,让咱们简单实现示例轮播图的HTML结构。
咱们将建立一个简单的轮播图,以显示遮罩效果。 咱们的轮播图将填满整个屏幕,咱们将添加一些将触发轮播图切换的箭头。 想法是覆盖轮播图,而后在动画结束时更改轮播图的z-index。 轮播图的结构以下:
<div class="page-view">
<div class="project">
<div class="text">
<h1>“All good things are <br> wild & free”</h1>
<p>Photo by Andreas Rønningen</p>
</div>
</div>
<div class="project">
<div class="text">
<h1>“Into the wild”</h1>
<p>Photo by John Price</p>
</div>
</div>
<div class="project">
<div class="text">
<h1>“Is spring coming?”</h1>
<p>Photo by Thomas Lefebvre</p>
</div>
</div>
<div class="project">
<div class="text">
<h1>“Stay curious”</h1>
<p>Photo by Maria</p>
</div>
</div>
<nav class="arrows">
<div class="arrow previous">
<svg viewBox="208.3 352 4.2 6.4">
<polygon class="st0" points="212.1,357.3 211.5,358 208.7,355.1 211.5,352.3 212.1,353 209.9,355.1"/>
</svg>
</div>
<div class="arrow next">
<svg viewBox="208.3 352 4.2 6.4">
<polygon class="st0" points="212.1,357.3 211.5,358 208.7,355.1 211.5,352.3 212.1,353 209.9,355.1"/>
</svg>
</div>
</nav>
</div>
复制代码
page view是咱们的全局容器,它将包含咱们的全部轮播图(project); 每个都包含一个标题和一个图例。 此外,咱们将为每张轮播图设置单独的背景图像。
箭头将做为下一个或上一个动画的触发器,并在轮播图中导航。
咱们来看看这个风格吧。
在这部分中,咱们将为咱们的效果添加CSS。
咱们将设置布局,其中包含一些居中的标题和页面左下角的导航。 此外,咱们将定义一些媒体查询来兼容移动设备的展现。
此外,咱们将雪碧图设置为全局容器中的不可见背景,以便咱们在打开页面时开始加载它们。
.demo-1 {
background: url(../img/nature-sprite.png) no-repeat -9999px -9999px;
background-size: 0;
}
.demo-1 .page-view {
background: url(../img/nature-sprite-2.png) no-repeat -9999px -9999px;
background-size: 0;
}
复制代码
每页轮播图都有一个不一样的背景图像:
.demo-1 .page-view .project:nth-child(1) {
background-image: url(../img/nature-1.jpg);
}
.demo-1 .page-view .project:nth-child(2) {
background-image: url(../img/nature-2.jpg);
}
.demo-1 .page-view .project:nth-child(3) {
background-image: url(../img/nature-3.jpg);
}
.demo-1 .page-view .project:nth-child(4) {
background-image: url(../img/nature-4.jpg);
}
复制代码
这固然是你将动态实现的东西,但咱们对效果感兴趣,因此让咱们保持简单。
咱们定义一个名为hide的类,只要咱们想隐藏某个元素就能够添加它。 类定义包含咱们用做遮罩的雪碧图。
知道一个帧是100%的屏幕,咱们的动画包含23个图像,咱们须要将宽度设置为23 * 100%= 2300%。
如今咱们使用步骤添加CSS动画。 咱们但愿咱们的雪碧图在最后一帧的开头中止。 所以,要实现这一目标,咱们须要比总数少一步,即22步:
.demo-1 .page-view .project:nth-child(even).hide {
-webkit-mask: url(../img/nature-sprite.png);
mask: url(../img/nature-sprite.png);
-webkit-mask-size: 2300% 100%;
mask-size: 2300% 100%;
-webkit-animation: mask-play 1.4s steps(22) forwards;
animation: mask-play 1.4s steps(22) forwards;
}
.demo-1 .page-view .project:nth-child(odd).hide {
-webkit-mask: url(../img/nature-sprite-2.png);
mask: url(../img/nature-sprite-2.png);
-webkit-mask-size: 7100% 100%;
mask-size: 7100% 100%;
-webkit-animation: mask-play 1.4s steps(70) forwards;
animation: mask-play 1.4s steps(70) forwards;
}
复制代码
最后,咱们定义动画关键帧:
@-webkit-keyframes mask-play {
from {
-webkit-mask-position: 0% 0;
mask-position: 0% 0;
}
to {
-webkit-mask-position: 100% 0;
mask-position: 100% 0;
}
}
@keyframes mask-play {
from {
-webkit-mask-position: 0% 0;
mask-position: 0% 0;
}
to {
-webkit-mask-position: 100% 0;
mask-position: 100% 0;
}
}
复制代码
如今咱们有了轮播图的结构和样式。 让咱们给它添加一些动效吧!
咱们将使用zepto.js进行此演示,这是一个很是轻量级的JavaScript框架,相似于jQuery。
首先声明全部变量,设置持续时间和元素。
而后咱们初始化事件,获取当前和下一张轮播图,设置正确的z-index。
function Slider() {
// Durations
this.durations = {
auto: 5000,
slide: 1400
};
// DOM
this.dom = {
wrapper: null,
container: null,
project: null,
current: null,
next: null,
arrow: null
};
// Misc stuff
this.length = 0;
this.current = 0;
this.next = 0;
this.isAuto = true;
this.working = false;
this.dom.wrapper = $('.page-view');
this.dom.project = this.dom.wrapper.find('.project');
this.dom.arrow = this.dom.wrapper.find('.arrow');
this.length = this.dom.project.length;
this.init();
this.events();
this.auto = setInterval(this.updateNext.bind(this), this.durations.auto);
}
/**
* Set initial z-indexes & get current project
*/
Slider.prototype.init = function () {
this.dom.project.css('z-index', 10);
this.dom.current = $(this.dom.project[this.current]);
this.dom.next = $(this.dom.project[this.current + 1]);
this.dom.current.css('z-index', 30);
this.dom.next.css('z-index', 20);
};
复制代码
咱们在箭头上监听点击事件,若是当前轮播图没有涉及动画,咱们会检查点击是否在下一个或上一个箭头上。 咱们在调整“下一个”变量的值的时候切换轮播图。
/**
* Initialize events
*/
Slider.prototype.events = function () {
var self = this;
this.dom.arrow.on('click', function () {
if (self.working)
return;
self.processBtn($(this));
});
};
Slider.prototype.processBtn = function (btn) {
if (this.isAuto) {
this.isAuto = false;
clearInterval(this.auto);
}
if (btn.hasClass('next'))
this.updateNext();
if (btn.hasClass('previous'))
this.updatePrevious();
};
/**
* Update next global index
*/
Slider.prototype.updateNext = function () {
this.next = (this.current + 1) % this.length;
this.process();
};
/**
* Update next global index
*/
Slider.prototype.updatePrevious = function () {
this.next--;
if (this.next < 0)
this.next = this.length - 1;
this.process();
};
复制代码
这个函数是咱们轮播图放映的核心:咱们将类“hide”添加到当前轮播图,一旦动画结束,咱们减小上一张轮播图的z-index,增长当前轮播图中的一个,而后删除隐藏 上一张轮播图的类。
/**
* Process, calculate and switch between slides
*/
Slider.prototype.process = function () {
var self = this;
this.working = true;
this.dom.next = $(this.dom.project[this.next]);
this.dom.current.css('z-index', 30);
self.dom.next.css('z-index', 20);
// Hide current
this.dom.current.addClass('hide');
setTimeout(function () {
self.dom.current.css('z-index', 10);
self.dom.next.css('z-index', 30);
self.dom.current.removeClass('hide');
self.dom.current = self.dom.next;
self.current = self.next;
self.working = false;
}, this.durations.slide);
};
复制代码
添加相应的类将触发咱们的动画,而后遮罩图像应用于咱们的轮播图。 主要思想是在动画功能中移动遮罩图像以建立过渡流。
就是这样! 我但愿这个教程对你有用,而且在建立你本身的酷遮罩效果时感觉到乐趣! 不要犹豫,分享你的做品,我很乐意看到他们!