zilan

zilan 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

zilan 发布了文章 · 2017-05-31

上传图片本地预览效果实现(兼容IE8)

最近项目里需要用到上传图片并预览的功能,于是写了个jQuery预览图片插件,下载地址。如果有需要的,可以直接下载。第一次写jQuery插件,如有不对之处,欢迎大家指正。下面是一些相关的知识点。

HTML5 File API

在HTML5 File API出现前,前端对于文件的操作的非常有局限性的。出于安全角度考虑,从本地上传文件时,代码是不可能获取文件在用户本地的地址。但是File API的出现,实现了这一功能。File API主要有以下几个接口:

  1. Blob

  2. File

  3. FileList

  4. FileReader

FileList API

当通过file控件获取文件后,可以通过该控件的files属性得到FileList对象。FileList对象里保存着选择的文件,即File对象。在MDN里有如下提示:

在Gecko 1.9.2之前,通过input元素,每次只能选择一个文件,这意味着该input元素的file
s属性上的FileList对象只能包含一个文件.从Gecko
1.9.2开始,如果一个input元素拥有multiple属性,则可以用它来选择多个文件.

因此需要注意,在默认状态下选择文件,每次FileList对象里只有一个File文件。
以上传图片为例。File对象保存了“name”,"size","type"等图片的信息。

<input id="fileItem" type="file">
var file = document.getElementById('fileItem').files[0];

FileReader API实现本地图片预览

FileReader用来异步读取本地文件
FileReader对象允许web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容。我们可以通过FileList获取上传的图片相关信息,但是想要实现本地预览还需要借助FileReader来实现,FileReader可以读取本地图片,并将图片数据转换成base64编码的字符串形式嵌入到页面中。

//创建一个FileReader对象
var reader = new FileReader();
//读取file文件;
reader.readAsDataURL(file);

FileReader提供了几个方法,如readAsText(),readAsDataURL(),readAsArrayBuffer(),分别表示用不同的数据格式来读取上传的文件,并将结果保存在result属性里。
在读取本地文件的过程中,FileReader提供了一些事件可供监听。如onprogress,onload,onerror,onabort等。在上传图片的过程中,常用到的有onprogress事件在读取数据过程中周期性调用,可以用来实现上传进度条效果,onload事件,当读取操作成功完成时调用。在我们实现上传图片的效果里,就有用到。

//当文件读取成功后,将结果保存到url变量里;
reader.onload = function(evt) {
    var url = evt.target.result;
}

最后,将该url赋值给img元素的src属性,便可以实现本地图片预览了。
关于兼容性,不兼容IE9及以下浏览器,其它主流浏览器一般都没有问题。

HTML5 URL API

URL对象用于生成指向File对象或者Blob对象的URL。使用URL的好处是可以不必把文件内容读取到JavaScript中而可以直接使用文件内容。如果通过URL对象来实现本地预览,那么只需将生成的File对象的URL传递给img元素的src属性即可。

当使用一个没有实现该构造器的用户代理时,可以通过 Window.URL
属性来访问该对象(基于 Webkit 和 Blink 内核的浏览器均可用 Window.webkitURL
代替)。

var url = window.URL || window.webkitURL;

createObjectURL()实现本地图片预览

URL对象有两个方法,分别是createObjectURL()revokeObjectURL()

  1. createObjectURL()的作用
    生成文件File对象或者Blob对象的URL对象,通过这个URL,可以访问到URL所指向文件的整个内容。

var src = url.createObjectURL(file);

在每次调用createObjectURL()方法的时候,都会创建一个新的对象URL,即使你已经用相同的对象作为参数创建过。在你不需要这些对象URL的时候,你应该通过调用 window.URL.revokeObjectURL()方法来释放它们所占用的内容。

  1. revokeOjectURL()的用法

url.revokeObjectURL(src); 

参数src是上述我们通过createObjectURL创建的URL对象。
关于兼容性,不兼容IE9及以下浏览器,其它主流浏览器一般都没有问题。在MDN里提到,这是一个实验中的功能。

图片预览兼容IE处理

IE9及以下版本不支持File API和URL API。因此需要做兼容处理。
在这里,我们需要用到document.selection。document.selection只有IE支持。代表了当前激活选中区,即高亮文本块,和/或文档中用户可执行某些操作的其它元素。selection 对象的典型用途是作为用户的输入,以便识别正在对文档的哪一部分正在处理,或者作为某一操作的结果输出给用户。
在用document.selection前,我们需要先创建选中区。如鼠标选中文本框,即是一个选中区。也可以通过js提供的select()方法创建一个选中区。创建了选中区后,我们就可以通过document.selection获取该选中区。如果要对选中区执行操作,则需要先调用createRange()方法。

//获取上传文件控件的值;
file.select();
var url = document.selection.createRange().text;

现有的获取IE低版本上传文件的value值一般都是这种方式,在IE中原本可以直接通过input的value值来获取上传图片的路径,但是在实际中很少看到使用。具体的大家可以去查查资料。
非IE6版本的IE由于安全问题直接设置img的src无法显示本地图片,但是可以通过滤镜来实现。

pic.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod='scale',data-original=\"" + reallocalpath + "\")";

到这里,图片本地预览基本就完成了。

查看原文

赞 7 收藏 19 评论 2

zilan 发布了文章 · 2017-02-26

less学习笔记

less要点:变量,混合,嵌套,函数&运算,扩展

一,变量

(1)less通过@来定义变量;如:@color:#333;
(2)不仅可以用变量来管理属性值,也可以用在选择器名称,属性名,URL以及@import语句中;
例一:选择器变量
less:

//定义一个选择器变量; 
@mySelector:banner;
//应用
.@{mySelector}{
    width:100px;
    height:100px;
}

编译后的css:

.banner{
    width:100px;
    height:100px;
}

例二:URL变量

@img:'../img';
//应用
.widget{
    width:100px;
    height:100px;
    background:url('@{img}/widget.png') no-repeat;
}

例三:属性变量

@property:color;
//应用
.widget{
   width:100px;
   height:100px;
   @{property}:#eee;
}

二,混合(Mixin)

类似于函数。混合可以将一个定义好的class A轻松的引入到另一个class B中,从而简单实现class B继承 class A中的所有属性。我们还可以带参数地调用,就像使用函数一样。
例一:无参

//定义一个color类
.color{
   color:#eee;
   background-color:#f00;
}
//应用
.widget{
   width:100px;
   height:100px;
   .color;
}

例二:有参

//定义一个color类
.color (@color:#eee){
    color:@color;
    background-color:#f00;
}
//应用
.widget{
    width:100px;
    height:100px;
    .color();//不传参时,即用默认的参数;
    .color(#0f0);//传入参数的情况
}

有些时候看到如下的用法:

.color () {
    color:#eee;
}

当你希望.color()不出现在css里,且又能引入其它类时,就可以这样写。
例三:
在媒体查询里的嵌套写法稍有区别,如下所示;
clipboard.png

三,匹配模式

匹配模式的写法类似于混合。它的作用类似于if语句。

.mixin(dark,@color) {
  color: darken(@color, 15%);
}
.mixin(light,@color) {
  color: lighten(@color, 15%);
}
//下面代码的作用是,不管匹配上面哪种模式,下面样式都会加进去。注意:第一个参数一定是@_,后面的每个参数都要加上
.mixin(@_,@color) {
width:100px;
height:100px;
}
.line {
  .mixin(dark,#FF0000);
}

编译后:

.line {
    color: #b30000;
    width: 100px;
    height: 100px;
}

四,嵌套

(1)在一个选择器中嵌套另一个选择器来实现继承;(&表示当前选择器的父选择器)
(2)媒体查询和嵌套媒体查询
less:

#header{
    background-color:#eee;
    overflow:hidden;
    .logo{
        float:left;
        width:50px;
        height:30px;
        a{
            display:block;
        }
    }
}

编译后:

#header{
    background-color:#eee;
    overflow:hidden;
}
#header .logo{
        float:left;
        width:50px;
        height:30px;
}
#header .logo a{
    display:block;
}

五,函数&运算

任何数值,颜色和变量都可以进行运算;less可以进行加、减、乘、除的运算;less提供了内置的函数,如Color函数,Math函数;

@width:50px;
#header{
width:@width + 50;
}

六,命名空间和访问器

有时候,出于组织的目的,或者为了提供一些封装,你会希望将你的mixins 组合在一起。以便稍候复用或者分发。
命名空间相当于一个混合的集合;可以在需要的地方引用单独的样式。

#bundle{
    .button{
        display:block;
    }
    .tab{……}
    .citation{……}
}

现在如果我们想在#header a中混合.button类,那么可以这样写:

#header a{
    #bundle > .button
}

需要注意的是命名空间内声明的变量将只作用于该命名空间,你会用它来引用一个mixin (#Namespace > .mixin-name)。但你不能这么做: (#Namespace > @this-will-not-work)。

七,作用域

less 中的作用域与编程语言中的作用域概念非常相似。首先会在局部查找变量和混合,如果没找到,编译器就会在父作用域中查找,依次类推。

八,注释

/*块注释*/
//行注释(不会输出到编译后的css文件中)

九,扩展

extend是一个less伪类,它会合并它所在的选择其和它所匹配的引用。
less:

nav ul{
    &:extend(.inline);
    background:blue;
}
.inline{
    color:red;
}

编译后:

nav ul{
    background:blue;
}
.inline,nav ul{
    color:red;
}

十,arguments变量

arguments变量包含了全部的传进来的参数。如果不想一个参数一个参数的写,那么可以用arguments参数。
less:

.border(@w:10px,@c:red,@xx:solid) {
    border:@arguments;
}
div{
    .border(20px);
}

编译后:

div{
    border:20px red solid;
}

十一,避免编译

有时候我们需要输出一些不正确的css语法或less不认识的专有语法。要输出这样的值我们可以在字符串前加上‘~’
例:

div{
    width:~' calc(100% - 35)';
}

十二,!important关键字

类似于css !important关键字。

查看原文

赞 1 收藏 3 评论 0

zilan 发布了文章 · 2017-02-15

js异步编程概念理解

单线程

Js语言的执行环境是“单线程”。所谓"单线程",就是指一次只能完成一件任务。如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任务,以此类推。
这种模式的好处是实现起来比较简单,执行环境相对单纯;坏处是只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。常见的浏览器无响应(假死),往往就是因为某一段Javascript代码长时间运行(比如死循环),导致整个页面卡在这个地方,其他任务无法执行。
Java是多线程编程语言,本人并没有接触过多线程的编程语言,在此就略过。

同步与异步

为了同步模式下的阻塞问题,Js语言将任务的执行模式分成两种:同步和异步。
同步模式,即上面所说的模式,任务按排列顺序执行;异步模式,其实就是延迟处理。在和HTML交互的过程中,会需要一些IO操作(典型的就是Ajax请求,脚本文件加载),如果这些操作是同步的,就会阻塞其它操作,用户的体验就是页面失去了响应。异步是通过异步函数实现的,如setTimeout()。

Javascript事件驱动

下面看一个例子。

var start = new Date();
setTimeout(function() {
var current = new Date();
var dvalue = current - start;
alert(dvalue + 'ms');
},500);
while(new Date() - start < 1000) {

}

我在google浏览器里,运行的结果是1002ms,因为setTimeout和setInterval的计时精度问题,不同的浏览器里得到的数值可能稍微有出入。但是这个数值肯定大于1000ms。
在这个例子里,js按顺序往下执行时,遇到setTimeout()函数,setTimeout()函数直接返回,里面的回调函数被放入到事件队列里。js接着往下执行while循环。当时间差>=1000时,跳出循环,执行完毕。此时js才会去处理队列里的事件。如果有适合“触发”(就像1000ms之前设定好的延迟500ms的延时事件)的事件,则调用该事件的处理函数。事件处理器返回后,我们又回到队列处。
在这里,我们要详细介绍下Javascript事件驱动机制。事件驱动一般通过事件循环(event loop)和事件队列(event queue)来实现的。假定浏览器中有一个专门用于事件调度的实例(该实例可以是一个线程,我们可以称之为事件分发线程event dispatch thread),该实例的工作就是一个不结束的循环,事件分发线程从事件队列中取出事件,调度事件的排队顺序,并不执行代码,注意回调函数是在Javascript的主线程中执行的,而非事件分发线程中,以保证事件处理不会发生阻塞。
在这里要注意“触发”和“执行”的区别。触发只是插入队列,执行才是真正的执行代码。这里的分发线程和主线程应该就是对应触发和执行这两个概念。
通过事件驱动机制,我们可以想象Javascript的编程模型就是响应一系列的事件,执行对应的回调函数。很多UI框架都采用这样的模型(例如Java Swing)。
暂时记录到这里,后续补充。

参考链接:
http://web.jobbole.com/82291/
http://www.ruanyifeng.com/blo...

查看原文

赞 2 收藏 10 评论 0

zilan 发布了文章 · 2016-12-19

移动站适配学习记录

最近在学习移动前端开发的相关知识,在这里做个记录,方便以后查看。

一,视口的知识

布局视口(layout viewport)

它的作用是给css布局限制一个最大宽度;

(pc/移动端)布局视口尺寸可以通过document.documentElement.clientWidth/clientHeight获取;

pc端

(1)屏幕尺寸

通过screen.width/height可以获取显示屏的宽和高;

clipboard.png

(2)布局视口

在pc端,css布局视口等于浏览器窗口的内在尺寸。
浏览器窗口的内在尺寸通过window.innerWidth/Height获取;window.innerWidth包含了滚动条的宽度;
在没有滚动条的时候,通过window.innerWidth和document.documentElement.clientWidth值是一样的;

clipboard.png

移动端

(1)布局视口

浏览器厂商为了让用户在小屏幕下网页也能够显示地很好,所以把布局视口宽度设置的很大,一般在 768px ~ 1024px 之间,最常见的宽度是 980px。

所以,在手机上,布局视口与移动端浏览器屏幕宽度不再相关联,是完全独立的,这个浏览器厂商定的视口被称为布局视口。

clipboard.png

(2)视觉视口(visual viewport)

在移动设备端,视觉视口可以简单的理解为设备的物理屏幕的可视区域。它用来承载布局视口。

视觉视口的值是固定的,只和设备的型号有关。它的大小和css像素值是相同的。可以通过window.innerWidth/innerHeight来获取。比如:

  iphone4 : 320*480px;

  iphone6 : 375*667px;

clipboard.png

(3) 理想视口(ideal viewport)

布局视口明显对用户是不友好的,完全忽略了手机本身的尺寸。所以苹果引入了理想视口的概念,它是对设备来说是最理想的布局视口尺寸。理想视口中的网页对用户来说,是最理想的宽度,用户进入页面的时候不需要缩放。

现在讨论所谓的『最理想的宽度』到底是多少?其实,如果我们把布局视口的宽度改成屏幕的宽度不就不用缩放了么。常见的可以如下设置viewport meta标签;

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" >

width
用来定义layout viewport的宽度;在这里,将device-width的宽度值赋给layout viewport;device-width即为设备宽的css像素个数;如果不指定width属性或者scale属性,或者移除viewport meta标签,则布局视口将恢复默认的值,如iphone为980px;

initial-scale
initial-scale用于指定页面的初始缩放比例,也可以实现理想视口。如下,表示将布局视口按device-width的1倍缩放。即布局视口大小等于设备宽度;
<meta name="viewport" content="initial-scale=1">

二,移动站适配的方法

1,通过rem布局 + 媒体查询实现

思路:在不同分辨率范围,给html设置不同的font-size大小。页面基于rem来布局,从而实现在不同分辨率的设备里看到相同的效果。
实现:
(1)设计稿基于iphone6,为750px宽。设置一个基数50(即在750px的设计稿里,html字体大小设置为50px,body字体大小设置为24px),750/50=15rem,即可以得到页面对应的rem数值。其它元素都可以通过px/50的方式转换成rem值来进行布局。
(2)计算出在不同分辨范围里的html字体大小,从而使页面自动调整样式。以min-width:320px为例,html字体大小为:320/15= 21.3333333px;即在320--359范围内,html字体大小为21.3333333px;在min-width:360px范围内,360/15=24px;
例子:【参考网站:http://m.suning.com/

clipboard.png

缺点:很难确定合适的临界点;

2,直接通过流式布局实现

思路:对于一些简单的移动站,直接可以用百分比来实现宽度自适应,高度用px固定即可
实现:
(1)顶部和底部,宽度100%,高度px设置,字体应用rem来设置,但是这里并没有设置不同分辨率下的html的字体大小,因此使用默认的字体大小16px来进行换算,字体还是固定大小。

例子:【参考网站:https://m.lagou.com/

clipboard.png

补充:对于列表,这里的布局实现方式如下,它是通过左边图片向左浮动,再给右边内容容器设置一个padding-left值来实现。在移动端,还可以运用flex弹性布局来实现。

clipboard.png

clipboard.png

3,利用JS来动态更改html字体大小

思路:假设拿到的设计稿是750px宽;设置一个基数100px,得到设计稿宽度为7.5rem;即可以得到html字体的计算方式:750/7.5 = 100px;利用js按此方式来动态更改html字体大小。
document.documentElement.style.fontSize = document.documentElement.clientWidth / 7.5 + "px";
实现:
(1)设计稿基于iphone6,为750px宽。页面元素的布局,以设计稿里的像素值除以100即可得到对应的rem值。

例子:【参考网站:http://3g.163.com/touch/all?n...

clipboard.png

4,利用JS来动态缩放布局视口

思路:前面几种方法,都需要添加"<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">",保证以理想视口(宽度等于css像素)来布局。在当前这种适配方案里,却是让布局视口的宽度等于设备的物理像素,然后将布局视口进行缩放,从而实现以理想视口来布局。
实现:
(1)设计稿基于iphone6,为750px宽。iphone6的物理像素为750px,设置一个基数10(即此时设计稿宽为10rem),html字体大小为:750/10 = 75px;根据这个字体大小可以计算出页面其它元素的rem值;
(2)device-width:指代比例为100%时(即scale=1)屏幕宽度的CSS像素数值。device-width的计算公式为:设备的物理分辨率/(devicePixelRatio scale);要保证device-width等于物理分辨率,需要获取devicePixelRatio值,这个值是固定的,因此,只要devicePixelRatio scale = 1,即可满足要求。
【个人理解:这里的device-width只是值和css像素值相同,设备的css像素值是不能改变的。device-width却可以调整大小。】
(3)iphone6的devicePixelRatio=2, scale = 0.5,原来布局视口等于设备物理像素等于750px,缩放0.5倍后,布局视口宽度为375px;等于理想视口。
“<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">”
例子:【参考网站:https://m.taobao.com/#indexht...

参考文章:
1,https://gold.xitu.io/entry/57...
2,http://blog.doyoe.com/2015/10...
3,https://github.com/riskers/bl...
4,http://www.cnblogs.com/well-n...

查看原文

赞 1 收藏 8 评论 0

zilan 关注了问题 · 2016-11-15

解决javascript如何合并多个数组

如题,已有两个数组

var array1 = ["a", "b"];
var array2 = ["c", "d"];

我要合并后变成下面这样:

var array= ["a", "b", "c", "d"];

应该用什么方法呢?

关注 1 回答 3

zilan 发布了文章 · 2016-11-08

移动端web开发基础概念

最近在了解移动端web开发的相关知识,有些概念总是模糊不清,这次花费了一些时间整体的梳理了一遍。

分辨率

分辨率可以从显示分辨率与图像分辨率两个方向来分类。显示分辨率(屏幕分辨率)是屏幕图像的精密度,是指显示器所能显示的像素有多少。图像分辨率则是单位英寸中所包含的像素点数,其定义更趋近于分辨率本身的定义。——360百科

显示分辨率指显示器所能显示的像素多少。如iPhone的分辨率:640x960,640x1136等。图像分辨率指单位英寸中所包含的像素点数(PPI)。如下图中PS新建文件的截图。

clipboard.png

PPI

PPI所属的上下文环境不同,意义也会不一样。当我们在谈论显示设备的PPI时,它指的是屏幕像素密度;和图片相关时,我们谈论的是打印时的分辨率或打印机的打印精度(在此种情况下,即是上文中提到的图像分辨率)。
在这里我们只关注屏幕像素密度。
让我们再次回到概念,每英寸的像素数量。英寸是长度单位,即它指的是长、宽、对象线每英寸里的像素数量。在1英寸的长度里,像素数量越多,PPI值越大。

clipboard.png

PPI有相应的计算公式:PPI=√(X^2+Y^2)/ Z (X:长度像素数;Y:宽度像素数;Z:屏幕尺寸)。
如下图,是苹果6s的部分规格参数,根据公式计算可以得出:PPI=√(1334^2+750^2)/ 4.7=325.6≈326。与苹果提供的参数相符。
在下图中,屏幕分辨率,屏幕尺寸,PPI都是官方给出的数据。可以知道,这三个数据都是固定的值,它只与手机的型号有关。因此,此处的像素应该是设备像素或物理像素。

clipboard.png

设备像素和css像素

设备像素

设备像素:定义了我们使用的设备的分辨率,一般来说可以通过screen.width/height来得到屏幕的大小。这个值是固定的,它只与设备有关。

css像素

css像素:又称设备独立像素(DIP),独立于设备的用于逻辑上衡量像素的单位。它的宽度不是一个固定的值。
比如在网页上创建一个width:500px;height:500px的div;当默认缩放比为100%的时候,一个css像素对应一个设备像素。当通过浏览器的缩放功能来改变缩放比为200%的时候,一个css像素的宽度等于两个设备像素的宽度。此时div的宽高仍然是500px * 500px。但是一个css像素的大小却等于4个设备像素的大小。

高清显示屏

高清显示屏起源于retina。它是一种由苹果公司设计和委托制造的显示屏。它的特点是,具备足够高的像素密度而使人眼无法分辨其中单独像素点的液晶屏。
如下图,假设屏幕大小为1英寸,左图是普通屏,右图是retina屏,可以看出,右图的像素密度要远大于左图。在常规的缩放比(100%)下,蓝色部分是需要在网页上展示的地方。根据一个css像素对应一个物理像素,可以知道,右图的显示部分视觉上看起来将会特别小。
为了让左右图在视觉上看起来一样,我们需要做的,就是让右边的图的1个css像素等于多个物理像素的大小。即将图片进行了一个放大处理。但是这样做的后果就是图片在视觉上变模糊了。
在移动端开发中,我们常常需要为高清显示屏准备2倍大小的图片,就是为了避免图片放大而发生模糊。

clipboard.png

设备像素比devicePixelRatio

devicePixelRatio = 物理像素 / 设备独立像素(css像素)
设备像素比可以用来区分普通显示屏和高清显示屏。devicePixelRatio值在1.5及以上的手机屏幕,是高清显示屏,为1.0为普通屏。
如,iPhone4的物理像素宽度为640px;css像素宽度为320px;可以得出devicePixelRation = 2;可以知道,iPhone4是高清显示屏。
在移动web开发中,为了让retina屏下的图片也可以清晰显示,我们需要给retina屏准备另一套大尺寸的图片,确保图片不会放大而变模糊。我们可以根据devicePixelRatio值来判断应该加载的图片尺寸。

.css{/* 普通显示屏(设备像素比例小于等于1.3)使用1倍的图 */ 
    background-image: url(img_1x.png);
}
@media only screen and (-webkit-min-device-pixel-ratio:1.5){
.css{/* 高清显示屏(设备像素比例大于等于1.5)使用2倍图  */
    background-image: url(img_2x.png);
  }
}
查看原文

赞 2 收藏 13 评论 0

zilan 发布了文章 · 2016-10-26

【译】css动画里的steps()用法详解

原文地址:http://designmodo.com/steps-c...
原文作者:Joni Trythall

我想你在css 动画里使用steps()会和我一样有很多困惑。一开始我不清楚怎样使用它,于是搜索出了两个案例:typing demo by Lea Verouanimated sprite sheet by Simurai.

这些例子很棒,帮助我开始理解这个特别的timming function,但是它们是如此优秀的例子,以至于在demo之外还是难以理解怎样使用steps()。

所以,我仔细研究了steps()并且做了一些动画demos用来帮助理解一些难点。

steps介绍

steps()是一个timing function,允许我们将动画或者过渡分割成段,而不是从一种状态持续到另一种状态的过渡。这个函数有两个参数——第一个参数是一个正值,指定我们希望动画分割的段数。

Steps(<number_of_steps>,<direction>)

第二个参数定义了这个要点 在我们的@keyframes中申明的动作将会发生的关键。这个值是可选的,在没有传递参数时,默认为”end”。方向为”start”表示一个左--持续函数,在动画开始时,动画的第一段将会马上完成。以左侧端点为起点,立即跳到第一个step的结尾处。它会立即跳到第一段的结束并且保持这样的状态直到第一步的持续时间结束。后面的每一帧都将按照此模式来完成动画。

方向为”end”表示一个右--持续函数。动画执行时,在每一帧里,动画保持当前状态直到这一段的持续时间完成,才会跳到下一步的起点,后面的每一帧都按照这个模式来进行,在最后一帧的起点,等到这一帧的持续时间结束,整个动画的执行也已经结束,执行动画的元素来不及跳到这一帧的终点,直接回到了整个动画起点,开始了第二次动画。每个选择本质上从一个不同的面移动这个元素并且将产生一个不同的位置在这个相同的动画里。
这面是示例图:

clipboard.png

动态解析图如下:
图片描述

填充模式和迭代次数的影响

在我们开始前,明白一个不同的填充模式或者迭代次数将会怎样影响steps()是非常重要的,例如”forwards”或者”infinite”的使用。如果我们有两辆车,使用相同的动画持续时间、相同的steps()值,但是其中一个设置(infinite),另一个填充(forward),终点的这两辆汽车看起来非常不同,即使他们从相同的轴点出发。

“forwards”的命令使这个动画元素保持着@keyframes里最后一个动画样式。在动画,里将它与steps()联系使这个动作出现,好像初始的静止状态没有计算到总的步数里。当它是”end”,好像这个车行驶了额外的步数超出了你的steps()的声明,取决于你怎样看待它。

这些讲解听起来还是很散乱,但是我们将在demos里慢慢讲解。(demo地址:http://designmodo.com/demo/st...)现在最重要的事情是留心这些变化将会怎样影响你的意图和steps数。下面是infinite VS forwards车:

clipboard.png

clipboard.png

steps demos

你可以点击这里查看demos,它由以下几个部分组成:

  • 纯css实现的闹钟

  • 一些节能的css车

  • 前进的熊爪印

  • 纯css实现的进度圆

css闹钟

clipboard.png

一个应用了steps()的闹钟演示。我们需要闹钟的指针旋转起来,但是不是圆滑连续的运动。使用steps()将允许我们模仿真实的闹钟的运动。

这里涉及到了一些数学知识,但是还不是很痛苦。我们需要秒针通过60步完成360度的旋转在60s的时间里。

clipboard.png

分针我们可以应用相同的@keyframes,只有改变动画的执行时间即可。分针转一圈,为3600s,即分针在3600s里,完成60步。

clipboard.png

申明:这只是一个css闹钟,并不能依赖这个闹钟来执行你的日常活动。

css cars

clipboard.png

css车演示了在steps()里使用"end"和"start"的不同。"start"使小车立即移动到一步的结束处并保持当前状态直到这一步的持续时间结束。看起来就好像使用了"start"的车的位置比使用"end"的车的位置更远,但是如果你给这两辆小车添加一个动画的延迟,你可以看到它们是从相同的起点出发的。

"end"会等到每一步的执行时间结束才会开始动画。第一辆车移动的时候,这是它的第二步,所以这两辆车没有机会同步移动。动画里白色的边框是动画当前的起始位置。

clipboard.png

熊脚印

clipboard.png

另一种更好的理解stpes()的方法是创建真实的步数。这个案例我们将会使用熊脚印。这个演示使用了由六个脚印组成的图片。这个图片被一个<div>覆盖,我们要用steps()移动这个<div>来显示出脚印,用来模仿实际的脚印。

没有使用steps()时,<div>将平滑的向右移动,这不是我们想要的效果。我们希望每个脚印可以立即完整的出现。

有六个脚印,我们需要向右移动<div>的长度为图片的整个宽度。

clipboard.png

我们的<div>将向右移动675px在7秒7步的时间里。每一步是96px宽。"end"表示我们的动画将保持它的初始状态,覆盖扬剧有的脚印直到第一步完成。

css进度圆

clipboard.png

在这个演示里我们使用"start"来动态改变不透明度。使用"start"制作一个百分比的可见度的变化。

clipboard.png

clipboard.png

所有的百分数在同一个<div>里,我们将这个<div>通过动画向上移动380px;初始值是"20%",我们需要通过四步移动<div>使数值为40%,60%,80%到最后的100%。

再次强调,使用"forwards"和"infinite"对步数的的作用是不同的。如果我们改变成"infinite",将不会出现"100%",因为"forwards"命令使动画在我们设置的步数外添加了额外的一步。"forwards"使动画保持结束时的状态,所以在步数执行完毕后,动画会跳到最后一帧的状态并保持不变。

结束语

steps() timing function确实难以理解,但是一旦你掌握它了,就会有很多便利。css function 允许我们将动画切割成清楚的步数,或者创建平滑的动画效果。
希望这些demos可以帮助你在动画里更好的理解使用steps()。

查看原文

赞 39 收藏 52 评论 4

zilan 关注了问题 · 2016-10-19

解决如何把gulp插件安装在全局,项目需要的时候调用

按教程提示在项目目录安装了gulp插件,但是提交到git的时候发现提示node_modules文件路径太长无法提交,现在想有没有一种方法把gulp插件安装在全局,当项目用到的时候就按需要加载,而不是每个项目都需要安装一篇gulp插件。

项目结构

这是我的项目结构,想要的是不要node_modules文件夹出现,通过一个文件配置来替代它。

关注 7 回答 4

zilan 关注了问题 · 2016-09-27

解决刚进公司的前端有问题请教

刚进公司半个月,在这半个月的时间里,做不不少事,但效率确实低,一是不熟悉公司前端框架,二是对工作方式不太熟悉。

当然,现在要好很多了,不过还是有很多问题。

公司项目是使用Java做的,前端采用了RequireJs来组织代码,AngularJS在前端处理数据,UI是自定义的一些组件。但工程项目的目录有点凌乱,没有划分dev目录,src目录不是开发目录,而是生产环境目录。

开发环境使用interllij idea,HTML和CSS我可以在熟悉的Atom里做,但Angular不得不在idea里调试。

我现在的问题是,如果能重构下前端的结构,使用我熟悉的编辑器,如Atom或Sublime,来做前端的事,在工程化工具的帮助下,实现在保存源码时能刷新页面。但idea是必须做热部署的,才可以看到修改后的效果。

请教下,有什么方法可以实现我的想法

关注 4 回答 3

zilan 提出了问题 · 2016-06-29

Media Queries 网站(http://mediaqueri.es/)上的图片的响应式布局实现原理?

如下代码,通过给每个图片设置了一个max-width和width,就可以保持图片在不同设备上的相同布局。
很好奇这里的margin-right,width,max-width这些数值是怎样计算出来的,刚好保证了图片等高来缩放?
clipboard.png

clipboard.png

clipboard.png

clipboard.png

clipboard.png

关注 2 回答 0

认证与成就

  • 获得 53 次点赞
  • 获得 3 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 3 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-02-09
个人主页被 540 人浏览