用CSS遮罩实现过渡效果的示例代码

所属分类: 网页制作 / CSS 阅读数: 1911
收藏 0 赞 0 分享

今天我们展示如何用CSS遮罩创建一个有趣又简单但吸引人的过渡效果。与裁剪一样,遮罩是另外一种定义可见性和元素组合的方式。在下面的教程中,我们将向你展示如何应用新属性实现现代转换效果。我们将使用steps()和位于图片之上的PNG实现一个有趣的过渡效果。steps()是一个timing function,允许我们将动画或者过渡分割成段,而不是从一种状态持续到另一种状态的过渡。这个函数有两个参数,第一个参数是一个正值,指定我们希望动画分割的段数。

注意: 该效果是高度试验性的,只被一些现代浏览器支持(Chrome、Safari、Opera)。

CSS Masks(CSS遮罩)

使用选定图像作为遮罩,用于显示元素的一部分的方法

W3C的候选推荐

支持以下版本:

Desktop

Mobile / Tablet

支持情况:

注意Firefox只是部分支持(它只支持内嵌的SVG遮罩元素),所以我们只能退一步希望所有的现代浏览器都尽快的提供支持。我们可以使用Modernizr来检查浏览器的支持情况。

创建遮罩图像

要实现遮罩过渡效果,我们需要一个图像来隐藏/显示我们底层图像的某些部分。该遮罩图像是具有透明部分的PNG图像。它自身应该是一个sprite image看起来像下面这样:

黑色部分显示当前图片,同时白色部分(透明部分)作为当前图像的遮罩,显示第二张图片。

为了创建sprite image,我们将视频导入到Adobe After Effects以减少视频的时间,移除白色部分并导出为PNG序列。为了将持续时间减为1.4秒(过渡时常),我们将使用Time strech效果。

要删除白色部分,我们将使用 extract键 设置白点到0。在下面的截图中,蓝色部分是背景是视频的透明部分。

最后,我们将其存储为PNG序列,然后使用Photoshop 或类似的图像处理软件将它生成了一个单一的图像。

我们将创建另一个“反向”sprite image,以产生相反的效果。你可以在演示文件的img文件夹中找到的所有的sprite image。
现在,我们已经创建了遮罩图像,让我们深入到这个变换示例的HTML结构中吧。

HTML

在这个例子中,创建一个简单的轮播图幻灯片来展示遮罩效果。轮播图将全屏显示,我们添加一些箭头用于触发幻灯片的过渡切换。思路是将要展示的幻灯片图像进行叠加,在每次过渡动画结束的时候,通过改变它们的z-index来切换。

下面是轮播图的HTML结构:

<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>

<div>作为整个容器,<div>是我们创建的幻灯片的各个部分,每一部分都包换了一个图片标题和图片说明。另外,每张幻灯片都设置了一张单独的背景图。其中的箭头部分用于触发下一张或者是上一张幻灯片。

The CSS

我们设置了一个传统的全屏轮播图布局,中心放置标题,左下角放置页面导航。此外定义了@media 查询以适应移动设备的样式。另外将sprite images设置为容器中不可见的背景,这样做是为了在打开网页的时候确保sprite images开始加载。

.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;
}

每一张幻灯片都有不同的background-image:

.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的class,当需要隐藏某张幻灯片的时候,将这个class添加上去。这个class定义了用于遮罩的sprite image。
每一帧是100%全屏展示,我们的动画包含23张图像,需要将宽度设置为23×100%=2300%。使用CSS3 animation的steps方式过渡,添加CSS动画。我们想让sprite停在最后一帧的开头。要做到这一点,需要的步数比总数少一步,也就是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;
  }
}

到这里,我们现在用了具有结构和样式的幻灯片了,接下来是让它更加具有实用性!

The JavaScript

在这个例子中用到了 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();
};

这个函数是这个demo的核心函数,当我们设置当前播放的这张幻灯片的class为hide时,动画一旦结束。将上一张幻灯片的z-index减小,增加当前幻灯片的z-index值,并移除上一张幻灯片的hide class。

/**
 * 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);
};

添加相应的class触发动画,进而将遮罩图像应用到幻灯片中。其主要思想是step animation过程中移动遮罩,以创建过渡流。

英文原文:Transition Effect with CSS Masks

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

更多精彩内容其他人还在看

CSS配合JavaScript做酷的动态页面效果

  利用CSS配合JavaScript的可以做很多更酷的动态页面效果,在本教程的最后给大家简单介绍一下CSS配合JS的应用。首先,要搞清楚事件和动作的概念。在客户端脚本中,JavaScript 通过对事件进行响应来获得与用户的交互。例如,当用户单击一个按钮或者在某段文字上移动鼠标
收藏 0 赞 0 分享

WEB标准,Web前端开发工程师必备技术列表

  想要打造并拥有一流的Web产品开发团队,在团队成员基础能力上一定要下功夫。对于Web前端产品开发来说,仅仅掌握Web1.0时代简单的"网页套接"是完全不够的。我结合自己的团队配备,特此罗列了Web前端产品工程师所涉及的技能列表如下:   通过许多实际项目,
收藏 0 赞 0 分享

用CSS制作Alpha滤镜测试板

alpha滤镜给制作网页特效提供了较大的创作空间,但由于它控制参数较多,在实际应用时,为了确定一组合适的参数值,不得不反复调整修改,在编辑窗口和预览窗口来回倒腾,甚是麻烦,本文介绍了一种简单的方法。制作一个“Alpha滤镜参数测试板”,在测试板上输入参数
收藏 0 赞 0 分享

非常流行的所谓的气泡窗口

普通的Alt无法自定义风格,而Sweet Titles通过JS脚本与CSS的集合.自定义了这种伪Alt风格. 前一段时间非常流行的,就所谓的气泡窗口(鼠标移到链接处出现的). 我们这里实现的用的是Sweet Titles的插件.显示效果完全由CSS控制.. 先下载Sweet Ti
收藏 0 赞 0 分享

CSS教程:li和ul标签用法举例

LI代码的格式化: A).运用CSS格式化列表符: ul li{ list-style-type:none; } B).如果你想将列表符换成图像,则: ul li{ list-style-type:none; list-style-image: url(/blog/images/
收藏 0 赞 0 分享

CSS教程:CSS中的定位(position)

  使用CSS来定位页面内层的位置,一直是比较难以掌握的事情,很多时候,往往被绝对定位的元素,总是以浏览器的左上角为坐标原点,此时,如果浏览器的大小改变,被定义的层就会偏离设计想要的位置,让人很挠头。   其实,要想控制好层的绝对定位,只要理解CSS中关于定位
收藏 0 赞 0 分享

CSS教程:盒模型(BOX Model)

  如果想熟练掌握DIV和CSS的布局方法,首先要对盒模型有足够的了解。每个HTML元素都可以看作一个装了东西的盒子,盒子里面的内容到盒子的边框之间的距离即填充(padding),盒子本身有边框(border),而盒子边框外和其他盒子之间,还有边界(margin),如图1所示。
收藏 0 赞 0 分享

无延迟翻滚的图形与CSS混合风格按钮

  在一个具有图形背景的按钮中添加CSS风格的文本,这种建立按钮的方法结合了具有CSS翻滚(CSS rollover)标记的开发速度和效率,从而有效地提高按钮外表图像的三维效果。   相比于常规的图形按钮,这些图形/CSS混合按钮可易于建立和载入,因为你只需要为空白按钮外面
收藏 0 赞 0 分享

css里expression实现界面对象的批量控制

用过css样式我们就知道, 可以定义一批对象的class属性来指定同一个样式来统一界面. 但如何统一同类型的对象的事件? 比如:界面有无数个 <img src="**.jpg"> 如何实现鼠标经过此图片, 图片的src变成是**_over.jpg?
收藏 0 赞 0 分享

CSS教程:水平对齐(text-align)

  水平对齐(text-align),用以设定元素内文本的水平对齐方式。   1.语法   text-align具体参数如下: 语法:text-align:left|right|center|justify 说明:设定元素内文本的水平对齐方式。 参数:left:左
收藏 0 赞 0 分享
查看更多