[转] impress.js学习
引子
断断续续用了好几天,终于把 impress.js 源码看完,作为刚入门的前端菜鸟,这是我第一次看 js 源码,最初还是比较痛苦的。不过还好,impress.js源码的注释相当清楚,每个函数和事件的作用都写得很详细,这让源码读起来更容易理解,此处手动给大神送糖果~~~
接下来就由我给大家分享下 impress.js 效果是如何实现的、以及我们怎么利用它来实现特效。
impress.js的实现
我们在用 impress.js实现特效时,会用到类似下面的代码:
<div id="its" class="step" data-x="900" data-y="3000" data-rotate="90" data-scale="4">
我们看到代码中有data-x,data-y等属性,实际上我们就是通过改变这些属性的值来实现PPT的跳转的。这些属性分别代表:
data-x:幻灯片的X坐标
data-y:幻灯片的Y坐标
data-scale:幻灯片显示的缩放比例
data-rotate:幻灯片旋转的度数
data-rotate-x:3D使用,设置它相对X轴旋转多少度
data-rotate-y:3D使用,设置它相对Y轴旋转多少度
data-rotate-z:3D使用,设置它性对Z轴旋转多少度我们来看看impress源码中的 rotate函数:
//'rotate'对给定数据构造旋转变换
//默认旋转顺序为X,Y,Z,可以将参数设定为true来倒转顺序
var rotate = function( r, revert ) {
var rX = " rotateX(" + r.x + "deg) ",
rY = " rotateY(" + r.y + "deg) ",
rZ = " rotateZ(" + r.z + "deg) ";
return revert ? rZ + rY + rX : rX + rY + rZ;
};
rotate函数的作用是将rotate对象转换成css使用的字符串。 用户自定义的数据通过data属性读取,并初始化给step对象。对应源码如下
:var data = el.dataset,
step = {
translate: {//对给定数据构造平移变换
x: toNumber( data.x ),
y: toNumber( data.y ),
z: toNumber( data.z )
},
rotate: {//对给定数据构造旋转变换
x: toNumber( data.rotateX ),
y: toNumber( data.rotateY ),
z: toNumber( data.rotateZ || data.rotate )
},
scale: toNumber( data.scale, 1 ),//对给定数据构造缩放变换
el: el
};
我们在编写HTML时,通过改变data的属性值实现页面切换,那么在源码中,又是怎么来实现的呢? 在impress.js源码中,主要通过三个事件来实现impress的运行,它们分别是impress:init,impress:stepenter和impress:stepleave,在了解这些事件之前,先明白 step 这个概念,一个step就相当于PPT中的一页,每切换一页就相当于切换一个step。每一次切换都会触发上面所提到的两个事件:impress:stepenter和impress:stepleave,从而达到页面跳转的效果。
我们在使用 impress.js的时候,需要调用impress.js中的impress().init()函数:`
<script type="text/javascript">impress().init();</script>
init() 函数是 impress 的主初始化函数,它的作用是初始化 impress API ,从而运行impress。在 init() 函数的结尾触发 impress:init事件,这样绑定上去的函数就会全部触发了。以下代码即是触发 impress:init事件:
triggerEvent( root, "impress:init", { api: roots[ "impress-root-" + rootId ] } );
};
Triggerevent()方法:触发指定对象的指定事件,并且立即执行该事件中的脚本。Triggerevent构造一个事件,该事件以 'eventnam'命名,用detail处理数据,并在el上执行。源码如下:
var triggerEvent = function( el, eventName, detail ) {
var event = document.createEvent( "CustomEvent" );
event.initCustomEvent( eventName, true, true, detail );
el.dispatchEvent( event );
};
接下来我们看看 impress:init事件上绑定了哪些函数:(1)为step添加一些有用的类:
root.addEventListener( "impress:init", function() {
// STEP CLASSES
steps.forEach( function( step ) {
step.classList.add( "future" );//所有尚未展示的 steps 都添加到都添加 `future` 类
} );
root.addEventListener( "impress:stepenter", function( event ) {
event.target.classList.remove( "past" );
event.target.classList.remove( "future" );
event.target.classList.add( "present" ); // 当某个step 被展示,`future`类会被移除,并被添加上 `present`类
}, false );
root.addEventListener( "impress:stepleave", function( event ) {
event.target.classList.remove( "present" );
event.target.classList.add( "past" );//当某个step结束时, `present` 又会被替换成`past`类
}, false );
}, false );
通过上面的方法,每个 step 都会处于 future
, present
和 past
三个状态中的一个,这样使得我们在切换PPT的时候可以前后任意切换。
上面代码中用到了addEventListener() 方法,该方法用于向指定元素添加事件句柄。语法如下:element.addEventListener(event,function,useCapture);
参数 event:必需,指定事件名,不要使用"on"前缀;
function:指定事件要触发时执行的函数;
useCapture:可选(布尔值),指定事件是否在捕获或者冒泡时执行。
可使用 removeEventListener() 方法来移除 addEventListener() 方法添加的事件句柄。
(2)添加hash变化支持:
root.addEventListener("impress:init", function(){
var lastHash = ""; // 将lasthash清空
// `#step-id`将被替换成`#/step-id`以防止浏览器在默认状态下滚动至hash表中所保存元素所在位置
//
// 而且添加hash的操作必须在动画结束以后进行, 因为在Chrome里会导致动画延迟
// BUG: http://code.google.com/p/chromium/issues/detail?id=62820
root.addEventListener("impress:stepenter", function (event) {
window.location.hash = lastHash = "#/" + event.target.id;
}, false);
window.addEventListener("hashchange", function () {
// 当某一step被展示时,location里的hash已经更新(就在上面几行)
// 所以hash change事件被触发,我们将在同一step上再一次调用`goto`方法。
// 为了避免这一情况,我们将存储上一次 hash 的结果并比较.
if (window.location.hash !== lastHash) {
goto( getElementFromHash() );
}
}, false);
// 开始
// 选择记录在url中的step地址,或者演示文稿的第一张step
goto(getElementFromHash() || steps[0], 0);
}, false);
window.location.hash: hash 属性是一个可读可写的字符串,该字符串是 URL 的锚部分(从 # 号开始的部分)。
location.hash可以用来获取或设置页面的标签值。
通过 window.location.hash=hash这个语句来调整地址栏的地址,使得浏览器里边的“前进”、“后退”按钮能正常使用。
(3)导航事件
键盘处理导航:
按键被按下时:
// 防止不允许被按下的键被意外按下
document.addEventListener("keydown", function ( event ) {
if ( event.keyCode === 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
event.preventDefault();
}
}, false);
preventDefault() 方法阻止元素发生默认的行为。
按键弹起时,触发impress动作(下一张或上一张):
document.addEventListener("keyup", function ( event ) {
if ( event.keyCode === 9 || ( event.keyCode >= 32 && event.keyCode <= 34 ) || (event.keyCode >= 37 && event.keyCode <= 40) ) {
switch( event.keyCode ) {
case 33: // 上翻页
case 37: // 小键盘左
case 38: // 小键盘上
api.prev();
break;
case 9: // tab键
case 32: // 空格
case 34: // 下翻页
case 39: // 小键盘右
case 40: // 小键盘下
api.next();
break;
}
event.preventDefault();
}
}, false);
处理在当前演示 steps 上产生的单击事件(当前step上是否存在超链接):
document.addEventListener("click", function ( event ) {
// 事件冒泡处理
// 检查单击的目标(及其祖先级容器)是否是超链接
var target = event.target;
while ( (target.tagName !== "A") &&
(target !== document.documentElement) ) {
target = target.parentNode;
}
if ( target.tagName === "A" ) {
var href = target.getAttribute("href");
// 如果指向某一连接,跳转至这一连接
if ( href && href[0] === '#' ) {
target = document.getElementById( href.slice(1) );
}
}
if ( api.goto(target) ) {
event.stopImmediatePropagation();//如果目标对象件被执行,将阻止剩下事件执行
event.preventDefault();
}
}, false);
event.stopImmediatePropagation() 方法阻止剩下的事件处理程序被执行,该方法阻止事件在 DOM 树中向上冒泡。
处理在当前演示 steps 上产生的单击事件:
document.addEventListener("click", function ( event ) {
var target = event.target;
// 查找距当前活跃step最近的不活跃step
while ( !(target.classList.contains("step") && !target.classList.contains("active")) &&
(target !== document.documentElement) ) {
target = target.parentNode;
}
if ( api.goto(target) ) {
event.preventDefault();
}
}, false);
处理触摸屏上上轻击屏幕左边或者右边的事件:document.addEventListener("touchstart", function ( event ) {
if (event.touches.length === 1) {
var x = event.touches[0].clientX,
width = window.innerWidth * 0.3,
result = null;
if ( x < width ) {
result = api.prev();
} else if ( x > window.innerWidth - width ) {
result = api.next();
}
if (result) {
event.preventDefault();
}
}
}, false);
当窗口大小改变时,重新计算窗口大小:
window.addEventListener("resize", throttle(function () {
// 强制激活当前step
api.goto( document.querySelector(".step.active"), 500 );
}, 250), false);
impress总共有4个API,分别是goto(), init(), next(), prev()。
impress的切换主要通过 goto()来实现,goto
API 跳转至以el
参数(索引,id或元素名)标记的step 。prev
API 按文档顺序跳回上一 step ,next
API 按文档顺序跳向下一 step 。
[转] impress.js学习的更多相关文章
- impress.js学习总结
impress.js是一个很有趣的用来替代PPT的展示用的js工具,它的灵感来自prezi 如果你要学习使用它,这里有很好的演示模板 使用它的第一步,下载 impress.js,引入到你的代码里,并执 ...
- Impress.js上手 - 抛开PPT、制作Web 3D幻灯片放映
前言: 如果你已经厌倦了使用PPT设置路径.设置时间.设置动画方式来制作动画特效.那么Impress.js将是你一个非常好的选择. 用它制作的PPT将更加直观.效果也是嗷嗷美观的. 当然,如果用它来装 ...
- impress.js初体验
概述 如果你已经厌烦了使用PowerPoint制作PPT,那么impress.js是一个非常好的选择,用它做的PPT更加直观,效果也非常的不错.装X是需要一定代价的,不过如果你是个前端爱好者那么一切就 ...
- 一统江湖的大前端(1)——PPT制作库impress.js
<一统江湖的大前端>系列是自己的学习笔记,旨在介绍javascript在非网页开发领域的应用案例和发现各类好玩的js库,不定期更新.如果你对前端的理解还是写写页面绑绑事件,那你真的是有点O ...
- 如何用impress.js写有逼格的ppt
概述 这是我学习课程impress让你的内容"舞"起来而做的总结和练手. 你可以点这里在线预览我做的ppt 注意:等加载完了之后,点击空格键翻页! 简化模板 下面是一个简化的模板 ...
- impress.js
介绍一下 impress.js是一个非常炫酷的幻灯片展示框架,依靠CSS3技术. impress.js使用起来非常简单,下面就来简单介绍一下其用法. Start 首先,当然要引入impress.js. ...
- impress.js 中文注释
impress.js 中文注释 玄魂 /** * impress.js *(本翻译并未完全遵照原作者的注释翻译) * Impress.js 是受 Prezi启发,基于现代浏览器的 CSS3 与 Jav ...
- 开胃小菜——impress.js代码详解
README 友情提醒,下面有大量代码,由于网页上代码显示都是同一个颜色,所以推荐大家复制到自己的代码编辑器中看. 今天闲来无事,研究了一番impress.js的源码.由于之前研究过jQuery,看i ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
随机推荐
- c++11 静态断言
c++11 静态断言 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #includ ...
- 用JS制作博客页面背景随滚动渐变的效果
今天颓了一会,用JavaScript给我的博客园博客写了一个页面背景随滚动而渐变的效果,做完之后自我感觉良好-- 下面就以我的博客园博客为例,介绍一下如何制作这个效果! 准备 [x] 申请博客园的JS ...
- 【数论Day1】 最大公约数(gcd)题目
20170529-3数论_gcd 题解: http://www.cnblogs.com/ljc20020730/p/6919116.html 日期 序号 题目名称 输入文件名 输出文件名 时限 内存 ...
- 面试题:get和post的本质区别
前言:相信小伙伴们面试时候一定都遇到过这个问题,即使没有遇到过,至少也听说过,网上资料一大片,大概每个人都能说出来一些.但是总感觉面试装逼不成功,所以就翻阅了部分资料,进一步整理了下. 一般当我们提到 ...
- Codeforces 468C/469E 易错点
#include <stdio.h> #include <stdlib.h> typedef long long ll; int main() { ll x=1e17; ll ...
- pyspider框架的599证书问题
使用PySpider 框架出现错误 HTTP 599: SSL certificate problem: unable to get local issuer certificate,如下 HTTP ...
- thinkphp自学笔记
什么是MVC? M:编写模型类-对数据进行操作 用作数据处理 V:编写HTML文件-将页面显示出来 网页视图 C:编写类文件 用作逻辑处理 ThinkPHP的MVC的特点是什么: 它比较灵活并不依赖 ...
- C#string与stringBuilder的区别
string的缺点是每次字符串变量的内容发生了改变时,都必须重新分配内存.你想想,如果创建一个迭代100000次的循环,每次迭代都将一个字符连接到字符串,这样内存中就会有100000个字符串,每个字符 ...
- CF876 D 树状数组
大意就是放n个硬币,每次放一个计算下这种情况下的操作次数,一个操作为从左到右扫描,如果一个硬币右边是空的,就将硬币后移,否则该次操作停止. 显然发现对于一个情况,我们只要考虑最右边的空位的左侧有几个硬 ...
- 8 Productivity hacks for Data Scientists & Business Analysts
8 Productivity hacks for Data Scientists & Business Analysts Introduction I was catching up with ...