最近给 nzoo 折腾官网,拿 angular2.0 + webpack 实现SPA,然后觉得最终打包后的出口文件有点大,用户首次访问会有一个时间较长的白屏等候界面,感觉体验不太好。

于是希望在用户下载整个 bundle 时能够先看到一个“加载中”的UI做过度,鉴于 nzoo 的LOGO也较简洁,便舍弃笨重的雪碧图+step动画的形式,转以 mask-image + transition动画来实现。

整体最终交互如下(模拟的是 2G 网速):

虽然界面简单,但整个动画仅仅使用了一张3.5kb大小的图片(戳我查看,注意是全白的会跟背景混一体):

如交互截图所示,我们希望在用户刚进入页面时,开始从底部给 logo 填色,持续10秒的 easeout 动画然后停在距离顶部还有一小部分未填色的地方。

接着在用户下载完 bundle 后,用 300ms 时间填完整个logo再执行 angular 应用启动脚本。

什么是 mask-image

擅长捣弄 Flash 甚至 AE 的朋友相信对“遮罩层”的概念会很清楚,都是指定某层的元件的轮廓/alpha通道来作为自己剪影的依据。在 Flash 中遮罩层只支持矢量,而AE则支持多种形式的遮罩(毕竟人家用来后期的嘛)。

另外FW和PS都支持alpha遮罩(PS中称为“蒙版”)。而今天要聊的css3中的 mask-image 则是以指定图片的透明度作为剪影依据的。

介个怎么理解呢?我们来张简单的示意图:

相信玩 flash 的童鞋会不屑地一笑,觉得是个好简单的事儿—— 底部搞个填满色的DOM由下往上运动,顶部固定放个轮廓层(png)剪影整个动画就行了嘛。

然而现实比较骨感—— mask-image 所指定的遮罩图会死死地固定在被遮罩元素上,可以理解为若元素动了那么遮罩图也会随着动。也就是说 flash 的那一套不适用于css3上。

此路不通换条道走—— 把动画改为 transition + background-position 来实现,而不靠元素本身瞎运动了。

我们现在手头有个 nzoo 的剪影,先看看填满整个logo 颜色需要怎么做,一共就俩步:

⑴ 放个DOM,给它配上 -webkit-mask-image 的样式指定遮罩图片;

⑵ 给 DOM上渐变色(得多次微调让渐变的角度、位置到位)。

于是初始化样式是这样的:

<style>mask-bg{mask-image: url(src/image/common/mask.png);-webkit-mask-image: url(src/image/common/mask.png);position: absolute;width:409px;height:158px;background-image: linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -webkit-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -moz-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);}
</style><mask-bg></mask-bg>

鉴于 firefox 还不支持在样式中配置 mask-image 特性,所以代码中我们没写 -moz-mask-image。(firefox的兼容后面说)

总之与 mask-image 样式结合前后的是酱子的:

留意 nzoo 的字样是有倾斜角度的,所以我们在 liner-gradient 中加了个 353deg 用于线性倾斜填充,这里填充的角度以及位置,均是后期微调得出的数据。

接着我们在其顶部安放另一个DOM(<mask-top>),用作完全未填色的 logo (底色为#EEE):

<style>mask-bg, mask-top{position: absolute;width:409px;height:158px;mask-image: url(src/image/common/mask.png);-webkit-mask-image: url(src/image/common/mask.png);}mask-bg{background-image: linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -webkit-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -moz-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);}mask-top{background-image: linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-image: -webkit-linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-image: -moz-linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);}
</style><mask-bg></mask-bg>
<mask-top></mask-top>

为实现动画再加上 background-position、background-size 和 transition 定义:

<style>mask-bg, mask-top{position: absolute;width:409px;height:158px;mask-image: url(src/image/common/mask.png);-webkit-mask-image: url(src/image/common/mask.png);}mask-bg{background-image: linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -webkit-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -moz-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);}mask-top{background-image: linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-image: -webkit-linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-image: -moz-linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-size: auto 300% ;-webkit-background-size: auto 300% ;-moz-background-size: auto 300% ;background-position: 0 -50%;transition: all 10s cubic-bezier(0, 0, 0.28, 1) 1s;}
</style><mask-bg></mask-bg>
<mask-top></mask-top>

其中 background-size 的配置用于拉长线性填充的渐进线,并初始化 background-position 的垂直距离为 -50%(即刚好整个剪影区域都是有填满#EEE的,剪影底部以下才则为rgba(0,0,0,0)的透明填充)。

所以后续我们通过动态改变 background-position 的垂直定位,把<mask-top>的渐进性由底部往上平移,从而逐步展示出其下方的<mask-bg>元素的内容,就能实现整个加载动画界面。

为了方便理解 <mask-top> 原理,我做了个效果图:

另外要留意的是我们给 transition 动画加了个1秒延迟,主要是为了方便客户端先下载遮罩图片再执行动画。

至于如何触发 transition 就不废话了,还是按老套数给父层元素动态加个 class 来实现:

        app.loading mask-top{background-position: 0 -8%;}app.loading-done mask-top{background-position: 0 0;transition: all 0.3s;}

    setTimeout(function(){document.querySelector('app').className='loading';},10);

注意这里的 app 是我给 <mask-top> 和 <mask-top> 外部过了一层自定义DOM <app></app>,原本只是用作后续挂载 angular 组件,现在咱把它用于存放挂载组件前先执行的加载交互元素。

在用户下载好 bundle 脚本之后(这时说明一切都loading好了),我们给 <app> 换上名为“loading-done”的类触发“把logo全部填满色”的 300ms 动画,也顺道延迟 300ms 再启动angular:

import {App} from '../component/App';
import {ROUTER_PROVIDERS} from 'angular2/router';
import {bootstrap} from 'angular2/platform/browser';document.querySelector('app').className='loading-done';
setTimeout(bootstrap.bind(this, App, [ROUTER_PROVIDERS]), 300);

于是在 webkit 浏览器中一切就如同一开始的交互动画一样顺利运行。

Firefox 和 Edge

Firefox 与 chrome 不同,对 mask-image 有另一套标准,需要 svg 加持,我们看下示例:

  <!-- SVG begins --><svg><!-- Definition of a mask begins --><defs><mask id="mask" maskUnits="userSpaceOnUse" maskContentUnits="userSpaceOnUse"><image width="400px" height="300px" xlink:href="mouse.png"></image></mask></defs><!-- Definition of a mask ends --><foreignObject width="400px" height="300px" style="mask: url(#mask);"><!-- HTML begins --><div class="element"><p>Lorem ipsum dolor sit … amet.</p></div><!-- HTML ends --></foreignObject></svg><!-- SVG ends -->

说白了就是往 svg 里嵌入 XHTML 来实现,细心看看其实也不复杂。我们可以稍微改下代码(主要是DOM结构)来做兼容:

    <style>app>div.loading-mask{position: absolute;top: 150px;left: 50%; margin-left: -204px;width:409px;height:158px;overflow: hidden;}.loading-mask mask-bg,.loading-mask mask-top{position: absolute;width:409px;height:158px;mask-image: url(src/image/common/mask.png);-webkit-mask-image: url(src/image/common/mask.png);}.loading-mask mask-bg{background-image: linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -webkit-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);background-image: -moz-linear-gradient(353deg,#89C027,#89C027 28%,#E96036 28%,#E96036 49%,#FEF158 49%,#FEF158 72%,#76C5EE 72%);}.loading-mask mask-top{background-image: linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-image: -webkit-linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-image: -moz-linear-gradient(bottom,#EEEEEE,#EEEEEE 60%,rgba(0,0,0,0) 60%);background-size: auto 300% ;-webkit-background-size: auto 300% ;-moz-background-size: auto 300% ;background-position: 0 -50%;transition: all 10s cubic-bezier(0, 0, 0.28, 1) 1s;}app.loading mask-top{background-position: 0 -8%;}app.loading-done mask-top{background-position: 0 0;transition: all 0.3s;}</style><app><div class="loading-mask"><svg width="409px" height="158px"><defs><mask id="mask"><image width="409px" height="158px" xlink:href="src/image/common/mask.png"></image></mask></defs><foreignObject width="409px" height="158px" style="mask: url(#mask);"><mask-bg></mask-bg><mask-top></mask-top></foreignObject></svg></div>
</app>

这样在 Firefox 中也能正常运行我们的加载动画了。

不过有趣的是,我在 caniuse 看到巨硬 Edge 是不支持 mask-image 的:

而实际用上 Firefox 这套后发现居然能在 Edge 上顺利运行了。

ok 大周末半夜三更的就跟大家唠嗑到这,想来我也许久没写样式软文了,共勉~

转载于:https://www.cnblogs.com/vajoy/p/5095511.html

巧用 mask-image 实现简单进度加载界面相关推荐

  1. html canvas直线进度条,js+HTML5 canvas 实现简单的加载条(进度条)功能示例

    本文实例讲述了js+HTML5 canvas 实现简单的加载条(进度条)功能.分享给大家供大家参考,具体如下: www.jb51.net canvas实现加载条动画 /* * 获取canvas, ca ...

  2. android自定义笑脸,Android实现笑脸进度加载动画

    最近看到豆瓣的笑脸loading很有意思,看一张效果图: 下面分析一下如何实现这样的效果: 1.默认状态是一张笑脸的状态(一个嘴巴,两个眼睛,默认状态) 2.开始旋转,嘴巴追上眼睛(合并状态) 3.追 ...

  3. 一款基于jquery带百分比的响应式进度加载条

    今天要给大家带来一款基于jquery带百分比的响应式进度加载条.这款加载条非常漂亮,而且带有进度的百度比,且在不同的百分比用的是不同的颜色.而且这款加载条采用了响应式设计,在不同的分辨率的显示器下完美 ...

  4. 最简单的加载器免杀思路

    本文首发于先知社区:https://xz.aliyun.com/t/9385 这部分源代码开放:https://github.com/MrWQ/HanGuang 最简单的加载器免杀思路 将加载器的变量 ...

  5. 数仓(十)从0到1简单搭建加载数仓DWS层

    数仓(一)简介数仓,OLTP和OLAP 数仓(二)关系建模和维度建模 数仓(三)简析阿里.美团.网易.恒丰银行.马蜂窝5家数仓分层架构 数仓(四)数据仓库分层 数仓 (五) 元数据管理系统解析 数仓( ...

  6. Android 自定义进度加载动画

    偶尔浏览一个android开发网站,发现进度加载动画比较不错,觉得挺有意思 就自己参考了下自己做了一个进度加载动画 效果图如下: 首选来看自定义动画 package com.itzb.paintdem ...

  7. android 动态水球,Canvas 制作动态进度加载水球详解及实例代码

    Canvas 动态进度加载水球 前言 之前看到一些球型的动态加载的效果,一直想自己动手做一个,正好这段时间重温了一个Canvas,所以就尝试了一下. 实现思路 关于水波的实现,使用了sin()函数,通 ...

  8. 【Unity使用UGUI实现王者荣耀UI界面(三)】登录界面以及加载界面优化

    [Unity使用UGUI实现王者荣耀UI界面(三)]登录界面以及加载界面优化 [只是用来玩玩的,不要太当真] 效果显示: zhans 1. 加载界面进度100%跳转登录界面 这个功能好做,只需要将上次 ...

  9. 【用Cocos Creator给暗恋的女生写一个游戏(3)】——游戏加载界面

    恰好今天Creator1.2发布,我们紧跟潮流,就用1.2开始做吧 X给游戏起了一个名字47-21,其中深意自己体会. (其实就是思琪名字的谐音,并且今年是她21岁的生日...当然你也可以理解为思琪爱 ...

最新文章

  1. VO 2 具体的过程
  2. Node.js 之 新手安装详解 及 npm 配置说明
  3. Vue.js 官方团队成员霍春阳新作,深入解析 Vue.js 设计细节【文末送书】
  4. jmeter测试客户端_如何在JMeter中执行客户端Web性能测试?
  5. img加载在IE11,chrome,FF下的不同
  6. 关于call()的this指向研究
  7. 1347 格子游戏 (并查集)
  8. vue 圆形百分比进度条_vue 圆形进度条组件解析
  9. python学习笔记(52周存钱挑战)
  10. 华为/阿里等公司招聘缩减!科技行业出现衰退?
  11. 用拼音输入希腊字母的方法
  12. 青龙脚本(七猫免费小说,附脚本)
  13. Chomsky文法分类
  14. format格式化输出
  15. C#通过ip地址取当前城市
  16. 如何使用普通的单反相机拍摄VR全景照片呢?
  17. SAS学习笔记之《SAS编程与数据挖掘商业案例》(3)变量操作、观测值操作、SAS数据集管理
  18. 机器学习---回归模型和分类模型的评价指标体系
  19. mathcad matlab,[讨论] (转载)我为什么特别推MathCAD?
  20. 网上邻居不能访问问题集锦

热门文章

  1. pikaqiu平台集成化漏洞练习
  2. java爬树方法,荒野求生徒手爬树技巧
  3. 如何提取音频从F4V
  4. qq音乐播放器2014最新版 v10.23.4377 官方版
  5. 消息验证码 MAC (HMAC、CMAC) 原理、特点
  6. 高三学生凭神经网络论文研究网络暴力!00后也要出道了?
  7. 情人节表白神器(成功率100%)
  8. 基于Spring+SpringMVC+MyBatis博客系统的开发教程(十二)
  9. php在表单调用函数后,从表单中调用php函数,并用结果完成表单 - php
  10. 移动大数据发展趋势包含几方面