在线预览 https://tympanus.net/Tutorials/CSSMaskTransition/ 下载源码
今天我们想向您展示如何使用 CSS Masks 创建一个有趣的过渡效果. 与剪切类似, 遮罩是定义可见性和与元素复合的另一种方式. 在下面的教程中, 我们将向您展示如何在简单轮播图中为过渡效果应用新属性. 我们将使用 steps()计时功能动画, 并在图像上移动遮罩 PNG 以实现有趣的过渡效果.
注意: 请记住, 这种效果还处于实验阶段, 只有现代浏览器支持(Chrome,Safari 和 Opera).
CSS Masks
使用所选图像来遮盖元素的一部分的方法
W3C 候选人推荐
支持以下版本:
桌面应用
移动端应用
可以在 https://caniuse.com/#feat=css-masks 上查看详细的支持情况
请记住, Firefox 只有部分支持 (它只支持内联 SVG 遮罩元素) 所以我们会有一个回退版本. 希望 CSS Masks 能尽快得到所有现代浏览器的支持. 请注意, 我们正在添加 Modernizr 以检查是否支持.
让我们一起愉快的开始吧!
创建遮罩图片
在本教程中, 我们将介绍第一个示例(演示 1).
为了使遮罩过渡效果起作用, 我们需要一个图像, 用于隐藏 / 显示基础图像的某些部分. 该遮罩图像将是一个 PNG, 上面有透明部分. 这个 PNG 将是一个雪碧图, 它看起来如下:
黑色部分将显示当前图像, 但白色部分 (实际上是透明的) 将是我们图像的遮罩部分, 将显示第二个图像.
为了创建雪碧图, 我们将使用此视频. 我们将其导入 Adobe After Effects 以减少视频的时间, 删除白色部分并将其导出为 PNG 序列.
要将持续时间缩短到 1.4 秒(我们希望转换的时间), 我们将使用时间拉伸效果(Time stretch effect).
要删除白色部分, 我们将使用 Keying -> extract 并将白点设置为 0. 在下面的屏幕截图中, 蓝色部分是我们合成的背景, 即视频的透明部分.
最后, 我们可以将合成的视频保存为 PNG 序列, 然后使用 Photoshop 或 CSS sprite https://spritegen.website-performance.org/ 生成单个图像:
这是一个雪碧图, 具有非常连贯的外观效果. 我们将为另一种效果创建另一个 "反向" 雪碧图. 您将在演示文件的 img 文件夹中找到所有不同的雪碧图.
现在, 我们已经创建了遮罩图像, 让我们简单实现示例轮播图的 html 结构.
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 样式
在这部分中, 我们将为我们的效果添加 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;
- }
- }
现在我们有了轮播图的结构和样式. 让我们给它添加一些动效吧!
JavaScript 表现
我们将使用 zepto.JS https://zeptojs.com/ 进行此演示, 这是一个非常轻量级的 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);
- };
添加相应的类将触发我们的动画, 然后遮罩图像应用于我们的轮播图. 主要思想是在动画功能中移动遮罩图像以创建过渡流.
就是这样! 我希望这个教程对你有用, 并且在创建你自己的酷遮罩效果时感受到乐趣! 不要犹豫, 分享你的作品, 我很乐意看到他们!
来源: https://juejin.im/post/5c32a5886fb9a049b506f8aa