整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

程序员的圈套,看了他写的javascript时钟,老

程序员的圈套,看了他写的javascript时钟,老板忍痛开始招设计师!

了程序员做的html5时钟,老板不得已立即招了个设计师,这或许是个圈套!

一直以来都觉得程序员的审美不行(包括我自己),但是后来接触了不少的程序员,感觉不是审美不行,而是,懒。当然一般来讲,很多事情就应该是美工来做的。先看这个HTML5/canvas时钟,界面很简单,仅仅是几个纯色的圆环,但是对于初学者来说,实现起来还是有点难度的,这个时间也是获取的本地时间,对于基础的javascript水平需要非常的扎实,而且对于canvas的属性,也需要很熟悉,主要还是javascript的逻辑要清晰,还有对于一些小细节的处理很重要,javascript算法倒是不多,想要更多HTML5/javascript特效游戏的朋友可以多关注我以前发的文章!以下附上源码!

如果有正在学习前端javascript的伙伴,不知道怎么学习,或者该学些什么才能找到工作的可以一起来我们的头条前端群570946165,一整套前端学习路线及系统学习资料已上传到群文件!

程序员做HTML5/javascript时钟源码

代码过长需要文档版源码来我的前端群570946165,源码已经上传了!

需要更多前端学习资料/视频/学习方法,请关注后,私信“学习”

5近两年在国内持续发酵,使得交互(interaction)这一概念从网站设计逐渐延伸到H5上。

就像鱼离不开水,H5离开了交互,便失去了HTML5语言所赋予页面形态的价值。说白了,如果H5弱化了交互,它充其量只是一个移动页面的滑动PPT,根本谈不上是H5。

“交互功能就像橡皮泥,只要发挥想象,它就能捏成各种形状。”这是iH5.cn某位不愿意露脸的专业设计师原话。只要发挥想象,即便是同一个交互功能,也能延伸出各式各样的戏法。

接下来以H5页面制作工具——iH5.cn为例,选用最常用的时间轴功能,一步步深入探究它能延伸出的各种戏法。

1.先别急着动手,时间轴究竟为何物?

如果对时间轴的概念不清晰,说再多也是白费,我们先来科普一下时间轴。

如果在初中电脑课上有学过Flash制作小汽车运动的朋友,看到时间轴的界面时应该会感到很熟悉。没错,时间轴的概念类似于Flash动画制作,通过关键帧控制对象在规定时间内的运动轨迹。

想用时间轴,请务必记住以下操作逻辑顺序:时间轴——对象——轨迹——关键帧——修改关键帧属性。

那么,时间轴最常见、最简单粗暴的应用是啥呢?

2.规律性的几何运动

只要打开时间轴的循环播放功能,它就变成了无限循环的时间单元,所以我们能用时间轴延伸出很多规律性的运动形态,打个比方——

(1)线性运动

就比如上面这个奔跑的男人,纯粹是单向线性往返运动,它的原理跟上面提到的用Flash做小汽车运动是一样的,我们只需在时间轴上,用多个关键帧控制这个男人的X坐标就能实现了——

说到这里,要跟大家分享一个小技巧。大家注意到这个男人其实是在做往返运动,前进跟倒退的轨迹是刚好相反的。

因此我们在这类往返运动制作时,只需做好前进的轨迹,然后在时间轴下插入一个“结束——时间轴反向播放”的事件,这样能减少很多工序,又能对称两个运动轨迹。

(2)圆周运动

跟线性运动相似,圆周运动只不过是在关键帧上调整素材的旋转角度,这是换汤不换药的,最常见的应用就是模仿现实生活中的手表/时钟,让秒针、分针做周而复始的圆周运动。

假如把线性运动跟圆周运动同时放在同一个时间轴下,那么恭喜你,一个简单粗暴的时间轴动画完成了——

说到这里,不禁想吐槽一下...为什么圆周运动式的玩法这么独特!这么好玩!怎么这么少设计师用?

它明明可以产生很多交互上的化学反应!无论是预加载的Loading页,还是过渡页,圆周运动式的时间轴动画都能给用户一种独特的心理预期,比如这种——

希望往后能看到这类时间轴应用的化学反应吧,咳咳,有点跑偏了,我们继续...

3.不存在规律的运动

其实说不存在规律的运动有点笼统,其实说成仿真式视频效果会比较合适,因为这类往往会让你分不清它到底是时间轴动画,还是视频

比如最近iH5.cn上那位专攻时间轴动画的设计师小牙,他不久前的《门窗都关了,你就给我看这个?》H5——

效果就跟用AE做的动画视频如出一辙,特别是那个全屏振动效果,这完全媲美AE上的wiggle(a,b)振动效果!只不过,小牙用的只是一个简单的“全屏振动”事件,就将这个效果复现了。

在这整套时间轴方案上看,设计师小牙让我们看到了时间轴的更多可能,用时间轴模仿动画视频,未尝不是一个很好的应用形式。

时间轴还能做什么?

4.用时间轴做高级动效

时间轴动效的原理和原生的动效组件相似,都是通过在单位时间内,改变元素的位置、大小、透明度、旋转角度等促成相应的动效效果。

可以是单位时间内控制单一属性,也可以是控制多个属性。

控制多个属性时,实现的动效效果更为惊艳!比如——

  • 橡皮糖式滑动效果(控制高度、Y坐标)

  • 重影效果(控制透明度、旋转角度)

  • 对折翻转效果(绕X坐标旋转)

  • 视差效果(控制剪切属性)

  • 360度物体展示(控制旋转角度、视距)

5.用时间轴做辅助

时间轴的灵活度很高,除了像上面提到的实现各种高大上交互,还可以作为辅助功能使用。此时可以将时间轴理解成导火线,用来引爆交互这颗重磅炸弹。

那么,它能“引爆”哪些交互?

  • 用时间轴的循环播放控制页面自动翻页

  • 时间轴用事件连接计数器,做成倒计时

  • 时间轴用事件连接动效组件,配合动效的延时触发,让动效的衔接更自然

  • 时间轴获取当前事件,制作按下1秒等敏捷类小游戏

当然时间轴的辅助性应用远不止于此,上面只是抛砖引玉,还有更多有趣&实用的技法,还需靠大家去发掘。

功能就放在那儿,看似是死的;但只要懂的思考,它就能活起来,甚至能让你的H5作品迸发出更多的光彩。

现在,你能联想出哪个功能的延伸应用了吗?

JavaScript里,我们已经会使用一些原生提供的方法来实现需要延时执行的操作代码,比如很多在线时钟的制作,图片轮播的实现,还有一些广告弹窗,但凡可以自动执行的东西,都是可以和定时器有关的。今天就来和大家分享一下,关于我们在JavaScript里经常会使用到的定时器方法

在JavaScript里,我们要学习四个定时器的使用方法,setTiemout、setInterval、setImmediate、requestAnimationFrame,一起来看看吧!


什么是定时器

JavaScript中提供了一些原生的函数方法来实现延时去执行某一段代码,这个就是定时器

下面我们来认识一下这些定时器

setTimeout:

设置一个定时器,在定时器到期后执行一次函数或代码段

 var timeoutId=window.setTimeout(func[, delay,param1,...]);
 var timeoutId=window.setTimeout(code[, delay]);

上面用到的关键词名称的意义:

timeoutId: 定时器ID

func: 延迟后执行的函数

code: 延迟后执行的代码字符串,不推荐使用原理类似eval()

delay: 延迟的时间(单位:毫秒),默认值为0

param1: 向延迟函数传递而外的参数,IE9以上支持

setInterval:

以固定的时间间隔重复调用一个函数或者代码段

 var intervalId=window.setInterval(func, delay[, param1,...]);
 var intervalId=window.setInterval(code, delay);

intervalId: 重复操作的ID

func: 延迟调用的函数

code: 代码段

delay: 延迟时间,没有默认值

setImmediate:

在浏览器完全结束当前运行的操作之后立即执行指定的函数(仅IE10和Node 0.10+中有实现),类似setTimeout(func, 0)

 var immediateId=setImmediate(func[, param1, param2, ...]);
 var immediateId=setImmediate(func);

immediateId: 定时器ID

func: 回调

requestAnimationFrame:

专门为实现高性能的帧动画而设计的API,但是不能指定延迟时间,而是根据浏览器的刷新频率而定(帧)

 var requestId=window.requestAnimationFrame(func);

func: 回调


举几个栗子加深思考


基本用法

 // 下面代码执行之后会输出什么?
 var intervalId, timeoutId;
 timeoutId=setTimeout(function() {
    console.log(1);
 }, 300);
 setTimeout(function() {
 clearTimeout(timeoutId);
     console.log(2);
 }, 100);
 setTimeout('console.log("5")', 400);
 intervalId=setInterval(function() {
     console.log(4);
 clearInterval(intervalId);
 }, 200);
 // 分别输出: 2、4、5

setInterval 和 setTimeout的区别?

// 执行下面的代码块会输出什么?
 setTimeout(function() {
    console.log('timeout');
 }, 1000);
 setInterval(function() {
    console.log('interval')
 }, 1000);
 // 输出一次 timeout,每隔1S输出一次 interval
 /*--------------------------------*/
 // 通过setTimeout模拟setInterval 和 setInterval有啥区别么?
 varcallback=function() {
 if(times++ > max) {
 clearTimeout(timeoutId);
 clearInterval(intervalId);
 }
     console.log('start', Date.now() - start);
 for(var i=0; i < 990000000; i++) {}
    console.log('end', Date.now() - start);
 },
 delay=100,
 times=0,
 max=5,
 start=Date.now(),
 intervalId, timeoutId;
 functionimitateInterval(fn, delay) {
    timeoutId=setTimeout(function() {
 fn();
 if(times <=max) {
 imitateInterval(fn ,delay);
 }
 }, delay);
 }
 imitateInterval(callback, delay);
 intervalId=setInterval(callback, delay);


如果是setTimeout和setInterval的话,它俩仅仅在执行次数上有区别,setTimeout一次、setIntervaln次。

而通过setTimeout模拟的setInterval与setInterval的区别则在于:setTimeout只有在回调完成之后才会去调用下一次定时器,而setInterval则不管回调函数的执行情况,当到达规定时间就会在事件队列中插入一个执行回调的事件,所以在选择定时器的方式时需要考虑setInterval的这种特性是否会对你的业务代码有什么影响?


setTimeout(func, 0) 和 setImmediate(func)谁更快?

 console.time('immediate');
 console.time('timeout');
 setImmediate(()=> {
     console.timeEnd('immediate');
 });
 setTimeout(()=> {
     console.timeEnd('timeout');
 }, 0);

在Node.JS v6.7.0中测试发现setTimeout更早执行


几道经典的定时器面试题

下面代码运行后的结果是什么?

 // 题目一
 var t=true;
 
 setTimeout(function(){
    t=false;
 }, 1000);
 
 while(t){}
 
 alert('end');

 // 题目二
 for(var i=0; i < 5; i++) {
 setTimeout(function() {
        console.log(i);
 }, 0);
 }
 
 // 题目三
 var obj={
    msg: 'obj',
 shout: function() {
 alert(this.msg);
 },
 waitAndShout: function() {
 setTimeout(function() {
 this.shout();
 }, 0);
 }
 };
 obj.waitAndShout();

在讲解上面面试题的答案之前,我们先要理解一下定时器的工作原理,以方便理解上面的题目


JS定时器的工作原理

这里将用引用How JavaScript Timers Work中的例子来解释定时器的工作原理,该图为一个简单版的原理图。

在这图中,左侧数字代表时间,单位毫秒;

左侧文字代表某一个操作完成后,浏览器去询问当前队列中存在哪些正在等待执行的操作;

蓝色方块表示正在执行的代码块;

右侧文字代表在代码运行过程中,出现哪些异步事件。

大致流程如下:

1.程序开始时,有一个JS代码块开始执行,执行时长约为18ms,在执行过程中有3个异步事件触发,其中包括一个setTimeout、鼠标点击事件、setInterval

2.第一个setTimeout先运行,延迟时间为10ms,稍后鼠标事件出现,浏览器在事件队列中插入点击的回调函数,稍后setInterval运行,10ms到达之后,setTimeout向事件队列中插入setTimeout的回调

当第一个代码块执行完成后,浏览器查看队列中有哪些事件在等待,他取出排在队列最前面的代码来执行

3.在浏览器处理鼠标点击回调时,setInterval再次检查到到达延迟时间,他将再次向事件队列中插入一个interval的回调,以后每隔指定的延迟时间之后都会向队列中插入一个回调

4.后面浏览器将在执行完当前队头的代码之后,将再次取出目前队头的事件来执行

在这也只是对定时器的工作原理做了简单的叙述,其实实际的实现处理过程会更加复杂。


面试题的答案

在我们理解了定时器的运行原理之后,接下来我们就基于运行原理的基础上,来看看上面的经典面试题的答案

第一题

alert永远都不会执行,因为JS是单线程的,且定时器的回调将在等待当前正在执行的任务完成后才执行,而while(t) {}直接就进入了死循环一直占用线程,不给回调函数执行机会

第二题

代码会输出 5 5 5 5 5,理由同上,当i=0时,生成一个定时器,将回调插入到事件队列中,等待当前队列中无任务执行时立即执行,而此时for循环正在执行,所以回调被搁置。当for循环执行完成后,队列中存在着5个回调函数,他们的都将执行console.log(i)的操作,因为当前JS代码上中并没有使用块级作用域,所以i的值在for循环结束后一直为5,所以代码将输出5个5

第三题

这个问题涉及到this的指向问题,由setTimeout()调用的代码运行在与所在函数完全分离的执行环境上. 这会导致这些代码中包含的this关键字会指向window (或全局)对象,window对象中并不存在shout方法,所以就会报错,修改方案如下:

 var obj={
     msg: 'obj',
 shout: function() {
 alert(this.msg);
 },
 waitAndShout: function() {
 var self=this; // 这里将this赋给一个变量
 setTimeout(function() {
            self.shout();
 }, 0);
 }
 };
 obj.waitAndShout();

需要注意的点

1.setTimeout有最小时间间隔限制,HTML5标准为4ms,小于4ms按照4ms处理,但是每个浏览器实现的最小间隔都不同

2.因为JS引擎只有一个线程,所以它将会强制异步事件排队执行

3.如果setInterval的回调执行时间长于指定的延迟,setInterval将无间隔的一个接一个执行

4.this的指向问题可以通过bind函数、定义变量、箭头函数的方式来解决