Bootstrap transition.js 插件详解
Bootstrap 自带的 JavaScript 插件的动画效果几乎都是使用 CSS 过渡实现的,而其中的 transition.js 就是为了判断当前使用的浏览器是否支持 CSS 过渡。下面先来简单了解下 CSS 过渡。
CSS 过渡
CSS 过渡是指在 CSS 属性发生改变时在一段时间内平滑地过渡,使用 CSS 伪类可以很方便地使用:
a {
color: #333;
transition: color 1s linear;
}
a:hover {
color: #36f;
}
这里给链接设置了一个 1秒的颜色过渡效果,当鼠标经过链接激活链接 :hover 状态的时候文字的颜色会从黑色平滑地变化为蓝色,鼠标移开时又平滑地变回来。
仅仅依靠伪类来使用过渡显得太单调了,使用 JavaScript 来动态添加删除 class 才能尽情地玩弄过渡:
/* 这是一个圆 */
.circle {
background-color: red;
border-radius: 50%;
height: 100px;
margin-left: 220px;
transition: transform 1s linear;
width: 100px;
}
/* 添加 left 类水平向左偏移 200 像素 */
.circle.left {
transform: translateX(-200px);
}
/* 添加 right 类水平向右偏移 200 像素 */
.circle.right {
transform: translateX(200px);
}
JavaScript 的工作就是简单的删除和添加 class:
function toLeft() {
$('.circle').removeClass('right').addClass('left');
}
function toRight() {
$('.circle').removeClass('left').addClass('right');
}
你让它往左,它不敢往右!demo上面的例子展示了当元素状态改变或者添加了某个 class 的时候过渡就开始发生了,那么如何知道过渡什么时候结束呢?
Transitionend 事件
想要知道过渡什么时候结束,就要监听 transitionend 事件(事件名称全是小写字母)。
$('.circle').one('transitionend', function() {
alert('过渡结束啦!');
});
这里使用 one 方法而不是 on 方法是为了避免 transitionend 事件多次执行。one 方法添加的事件回调只会执行一次,更多信息参考官方 API。
不过这只是标准的事件名称写法,在标准之前浏览器有各自的实现方式以及不同的事件名称(比如低版本的 Chrome 和 Safari 的该事件名称就叫 webkitTransitionEnd),所以为了兼容更多的浏览器,一种比较笨拙的方式可以写成像下面这样:
$('.circle').one('transitionend webkitTransitionEnd oTransitionEnd otransitionend', function() {});
很长一串,而且这种写法还有一点问题!
在这里可以看到为什么是上面这些事件名称,而没有 msTransitionEnd 之类。
为了根据浏览器更有针对性地添加 transitionend 事件回调,而不是像上面那样一骨碌地全加上,就需要先判断一下该浏览器到底支持哪种 transitionend 事件名称,判断方法则是根据浏览器支持 CSS 过渡的属性名称而定:
var el = document.createElement('bootstrap'); // 创建一个元素用于测试
if (el.style.transition !== undefined) {
// 判断元素的 style.transition 属性如果存在
// 则以此类推该浏览器支持标准的 CSS transition 属性以及标准的 transitionend 事件
} else if (el.style.WebkitTransition !== undefined) {
// 判断元素的 style.WebkitTransition 属性如果存在
// 则该浏览器支持替代的 webkitTransitionEnd 事件
} else {...}
按照当前的主流浏览器趋势总共需要判断四种不同前缀的属性名称:
el.style.transition
el.style.WebkitTransition
el.style.MozTransition
el.style.OTransition
判断方式就是这样,废话就说到这里,直接上正牌代码,Bootstrap transition.js 内部的判断函数:
function transitionEnd() {
// 创建一个元素用于测试
var el = document.createElement('bootstrap');
// 将所有主流浏览器实现方式整合成一个对象,用于遍历
// key 是属性名称
// value 是事件名称
var transEndEventNames = {
WebkitTransition : 'webkitTransitionEnd',
MozTransition : 'transitionend',
OTransition : 'oTransitionEnd otransitionend',
transition : 'transitionend'
};
// 循环遍历上面那个对象,判断 CSS 属性是否存在
for (var name in transEndEventNames) {
if (el.style[name] !== undefined) {
return { end: transEndEventNames[name] };
}
}
return false;
}
执行该函数可以得到一个对象 {end: 'transitionend'} 或者 false (表示浏览器不支持 CSS 过渡),该对象的 end 属性保存着浏览器所支持的 transitionend 事件对应的名称:
var transition = transitionEnd();
比如我使用低版本的 Chrome 浏览器的话,那么得到的对象就是 {end: 'webkitTransitionEnd'} 这样;如果使用 IE 8 则是 false,然后就可以添加该事件的回调函数了:
// 如果 transition 为 false 则不添加事件回调
transition && $('.circle').one(transition.end, function() {});
为了与 jQuery 保持一致,将该返回结果赋值到 $.support.transition 上:
$.support.transition = transitionEnd();
// 使用方式是类似的
$.support.transition && $('.circle').one($.support.transition.end, function() {});
EmulateTransitionEnd
事件名称的问题基本上解决了,但是这个事件有个问题就是有时根本不会触发,这是因为属性值没有发生变化或没有绘制行为发生。要确保每次回调都会被调用,我们增加一个定时器即可:
$.fn.emulateTransitionEnd = function(duration) {
var called = false; // transitionend 事件是否已触发标识
var $el = this;
$(this).one($.support.transition.end, function () {
called = true; // 表示已触发
});
var callback = function() {
if (!called) {
$($el).trigger($.support.transition.end); // 未触发,强制其触发
}
};
setTimeout(callback, duration); // 一段时间后检测是否触发
return this;
};
该方法的作用是一段时间(就是过渡持续的时间 transition-duration )过后如果 transitionend 事件没有发生则强制在该元素上触发这个事件。
$('.circle').one($.support.transition.end, function() {});
$('.circle').emulateTransitionEnd(1000); // 这个时间是过渡持续的时间
这样确保过渡之后一定会有回调。到这里,基本上就差不多了,不过 $.support.transition.end 好恶心啊!能不能像添加其它事件回调一样使用事件名称字符串的形式,比如 'click',当然可以。
自定义事件
$(function () {
$.support.transition = transitionEnd();
// 支持过渡的时候才执行后面的代码
if (!$.support.transition) {return;}
$.event.special.bsTransitionEnd = {
bindType: $.support.transition.end,
delegateType: $.support.transition.end,
handle: function (e) {
if ($(e.target).is(this)) {
return e.handleObj.handler.apply(this, arguments);
}
}
};
});
添加事件回调的时候就可以像这样:
$('.circle').one('bsTransitionEnd', function() {})
.emulateTransitionEnd(1000);
其它
CSS 动画同样也有一个 animationend 事件,同时还有 animationstart 和 animationiteration 事件,可以参考这种方式自己写一个。
参考资料
- All you need to know about CSS Transitions
- Using CSS transitions
- Detecting CSS Animation Completion with JavaScript
Bootstrap transition.js 插件详解的更多相关文章
- Bootstrap transition.js 插件
Bootstrap transition.js 插件详解 Bootstrap 自带的 JavaScript 插件的动画效果几乎都是使用 CSS 过渡实现的,而其中的 transition.js 就 ...
- 转载 JS组件Bootstrap Select2使用方法详解
JS组件Bootstrap Select2使用方法详解 作者:懒得安分 字体:[增加 减小] 类型:转载 时间:2016-01-26我要评论 这篇文章主要为大家介绍了JS组件Bootstrap Sel ...
- 使用bootstrap的JS插件实现模态框效果
在上一篇文章中,我们使用 js+css 实现了模态框效果,在理解了模态框的基本实现方法和实现效果后,我们就要寻找更快捷的方法,又快又好的来完成模态框开发需求,从而节约时间,提高效率.一个好的轮子,不仅 ...
- Bootstrap Table使用方法详解
http://www.jb51.net/article/89573.htm bootstrap-table使用总结 bootstrap-table是在bootstrap-table的基础上写出来的,专 ...
- Uploadify 上传文件插件详解
Uploadify 上传文件插件详解 Uploadify是JQuery的一个上传插件,实现的效果非常不错,带进度显示.不过官方提供的实例时php版本的,本文将详细介绍Uploadify在Aspnet中 ...
- js对象详解(JavaScript对象深度剖析,深度理解js对象)
js对象详解(JavaScript对象深度剖析,深度理解js对象) 这算是酝酿很久的一篇文章了. JavaScript作为一个基于对象(没有类的概念)的语言,从入门到精通到放弃一直会被对象这个问题围绕 ...
- Google自写插件详解
谷歌插件详解,跳转至个人主页查看. GoogleExtension
- Maven系列第6篇:生命周期和插件详解,此篇看过之后在maven的理解上可以超越同级别90%的人!
maven系列目标:从入门开始开始掌握一个高级开发所需要的maven技能. 这是maven系列第6篇. 整个maven系列的内容前后是有依赖的,如果之前没有接触过maven,建议从第一篇看起,本文尾部 ...
- ThreeJS系列1_CinematicCameraJS插件详解
ThreeJS系列1_CinematicCameraJS插件详解 接着上篇 ThreeJS系列1_CinematicCameraJS插件介绍 看属性的来龙去脉 看方法作用 通过调整属性查看效果 总结 ...
随机推荐
- IIS 6中mimemap属性的默认设置
Collapse this tableExpand this table Extension MIME type .ra audio/x-pn-realaudio .sv4crc applicatio ...
- Java多线程系列--“JUC集合”05之 ConcurrentSkipListMap
概要 本章对Java.util.concurrent包中的ConcurrentSkipListMap类进行详细的介绍.内容包括:ConcurrentSkipListMap介绍ConcurrentSki ...
- [OpenCV] Samples 03: cout_mat
操作Mat元素时:I.at<double>(1,1) = CV_PI; /* * * cvout_sample just demonstrates the serial out capab ...
- 一道 google曾出过的笔试题:编程实现对数学一元多项式的相加和相乘操作(1)
数学中一元n次多项式可表示成如下的形式: Pn(x)=p0+p1x+p2x^2+…+pnx^n (最多有 n+1 项,n +1 个系数唯一确定她) (1)请设计一套接口用以表示和操 ...
- [转载]UML时序图总结
前言 在我的工作中,用的最多的就是时序图了.可能由于工作的原因,我也是最喜欢画时序图了,很清楚,很明了,什么时候发送什么消息,到达什么状态,一下子就展示在你的脑海里,对于消息驱动的程序来说,是再好不过 ...
- 机器学习&数据挖掘笔记_12(对Conjugate Gradient 优化的简单理解)
数学优化方法在机器学习算法中至关重要,本篇博客主要来简单介绍下Conjugate Gradient(共轭梯度法,以下简称CG)算法,内容是参考的文献为:An Introduction to the C ...
- ansible写一个简单的playbook
前言 实现的功能很简单,就是通过ansible批量完成某个账户sudo权限的开通或关闭 目录结构 ├── group_vars #放置各种变量的目录,我这里没用 ├── hosts #主机和组配置,默 ...
- TinyOS和Deluge的安装模拟(二)
TinyOS的安装 TinyOS的安装是一件麻烦的事情,它不像其他的开发环境那样配置简单.要想成功安装好TinyOS,需要选择好PC操作系统,TinyOS安装文件的版本,工具链的版本…….总之,安装过 ...
- LeetCode - Flatten Binary Tree to Linked List
题目: Given a binary tree, flatten it to a linked list in-place. For example, Given 1 / \ 2 5 / \ \ 3 ...
- Android 获取可靠的手机编码
项目中出现了将设备和用户信息进行绑定的需求.最先想到的是IMEI串码和IMSI串码.手机登陆的时候一直都没有问题.换了一个平板中之后IMEI和IMSI串码都获取不到了.后来查了一下原因,是因为平板上是 ...