jQuery powerSwitch万能slide(切换)插件

这篇文章发布于 2013年11月10日,星期日,23:20,归类于 jQuery相关。 阅读 209938 次, 今日 11 次 85 条评论

 
测试页面、demo页面、API文档

测试页面
demo页面: /demo/
API文档: /api/index.html

一、powerSwitch诞生的背景

2010年的时间,差不多整整3年之前,我由于懒惰,写了个jQuery插件,名叫“powerFloat”的万能浮动插件,顾名思意,就是可以实现任意的浮动层相关效果。

结果,发现,原来大家都好这一口,一本万利,一方通行,一夫当关万夫莫开,一个插件万种交互。结果介绍此插件的文章成了自己最热门,评论最多的文章。

我突然想起了新浪微博,也是万能的,什么都有,或许中国人就好“万能”这口。

什么都没有的twitter

其实,想写一个万能切换插件的想法由来已久。之前,我是将“展开收起效果”,“选项卡切换效果”,“跑马灯切换效果”分开成独立的小组件来处理的。可能有人会疑问,这不挺好的。配合特定的路由加载机制,很适合多人协作,扩展之类。

然,千万不能把盖茨,布斯之类的所有做法习惯应弄在自己身上,他们只是少数的特例。其实,大部分乔布斯那种style的人都已经被时代掩埋(渣子都找不到了)(观《乔布斯传》有感)。

So,千万不能因为东西宣传的好,或者说是大公司出品,就用之(研究与学习是很推荐的)。

人的眼界很重要,这会让你看事物的角度不同。是抬头往四周看呢,还是居高临下观摩?前者身在庐山,后者审视夺度。

官二代们,富二代们,一般从小锦衣玉食,不知民间疾苦。身为百姓的你,如果一味follow他们的调调,岂不苦上加苦?

不是所有的项目都是大项目,不是所有的企业都是N多前端。实际上,大多数的站点,大多数的小团队是0个专业前端,临时找个外包,或者后端顶上,数不胜数。

即便是有一两个专业前端的团队,过度的颗粒化也是不适合,或者说没必要,反而留坑。所谓多大的骡子套多大的圈。按照我以前的经验,最基本的问题就是记忆成本,即使各个插件出自一人之手,其API名称也会有所差异,因此,常常记不住是A还是B. 有点类似于小时候,分辨冬瓜、西瓜、南瓜的感觉。

因此,就想过,可不可以把这些切换通过特定的设计,全部整合到一起。

上个月,接触前端组模块化的switchable方法(依赖之可延伸出选项卡,跑马灯等组件),跟之前kissy 1.3停止维护的switchable类似。
kissy 1.3停止维护的switchable

//zxx: 看完恒大最后10分钟归来…

笔头不息,吐槽不止。我是个非常崇尚自由的人,因此,对这种诸多限制的组件很无感,一个字表示就是“哦”。拿kissy举例,或许为了aria,其必须需要匹配特定的DOM结构,会牵扯内部的一些UI CSS. DOM限制,UI限制,如此多的限制,实际上更适合自家人使用。想普世,想众人皆用,怕是只能停留在愿景层面。或许正是因为这些限制,此组件后来才停止维护的。

// zxx: ① 强限制关系容易出bug. 例如:.example > a {} 这个选择器,如果HTML部分,a标签外面嵌套其他标签以实现更精致的效果,则bug产生。可参考bootstrap中组件CSS的强关系命名。

DOM限制以及UI限制会扼杀设计师的创意。例如交互设计师想了一个很有创意的切换效果,但要想套用这个组件就……鞭长莫及,要么你改,要么我改;或者设计师设计了一款更精致的皮肤,结果组件生成的HTML不够用,或组件要求的HTML层级实现不了,咋办?你割我一刀,或我割你一刀~~

前端组的switchable组件也有类似的问题,不管设计师,UI先行,DOM结构限定。一群理工科男的逻辑YY(虽然我也是),或者可能是借鉴,某些团队这么搞的,恩,我们可以借鉴学习下。

越想越鄙视!//zxx: 导演,回头这段要记得剪掉哈~~

总之,就是觉得前端组的切换组件不靠谱(以后我肯定会介入重整这一堆堆的代码),这成为我决心把自己酝酿很久的万能切换插件整出来的导火索。不同的思想,不同的设计理念,面向不同的人群,就整出个比你靠谱,大家更喜欢的东西。

于是,就有了前后历时20天,除了钓鱼以外一切业余时间完成powerSwitch的故事。之前的powerFloat连代码、测试、写文章就10天,而且还是三年之前的自己写的(技术)。可见,这里的powerSwitch插件要比powerFloat更难设计,自己也更重视。

OK,开始进入正题。

//zxx: 啊,好久没在开头唠叨这么长的内容了,好爽!

二、powerSwitch与分类学

//众人:博主,你是个大忽悠,不是说正题了吗!
//zxx: 骚瑞啊,太久没写文章了,没忍住~~However……这也可以看成正题~~

分类学是区分事物类别的学科。要分类,需要辨别事物的异同。

万能切换插件,就是要整合各种切换效果,是齿轮式的交错,而不是,一个一个的堆积木。因此,需要寻找各种切换的共性或者是一种可以统一解释的模式。

不懂?举个简单例子,有如下场景:

1人OOXX, 2人OOXX, 3人OOXX, 一群人OOXX

请问:如何用一种统一的解释,描述上面的场景?

我们可以用P解释,于是就有1P, 2P, 3P, 群P.

那切换呢?有如下场景:

广告文字自动播, 更多-展开与收起, 选项卡, 跑马灯,手风琴

请问:如何用一种统一的解释,描述上面的场景?

因为,只有有了一致性的解释,才能共性整合;才不是独立堆砌。

我自己是通过映射方式(触发按钮与切换列表)解释的:

  • 广告文字自动播,选项卡,手风琴属于“1对1映射”关系。如:一个选项卡,对应一个面板~
  • 更多-展开与收起属于“1对多映射”关系。因为:点击更多可以一次展开多个内容。
  • 跑马灯属于“多对1”的关系。因为:前进与后退实际上对应的是同一列表元素们。

这种映射解释是自己坐地铁回家,画拓扑图的时候,想到的。这种解释与分类使得各种切换方法交错的同时不会产生干扰。

但是,鄙人属于逻辑YY的理工男,因此,肯定会有更艺术、更better的分类归纳,欢迎提出您的看法~~

三、powerSwitch与动态API设计、匿名API设计

动态API
一般的JS插件的API设计都是“你是什么就做什么”,例如kissy的switchable:
switchable API参数

每个配置的API的作用很唯一,例如circular就表示是否循环播放。这非常符合正常思维,但有一个什么问题呢?

看上去API丰富,实际上,API名称啰哩吧嗦、洋洋洒洒,根本就记不住,就算来块士力架也是无能为力。于是,只能是查文档,这里有个这个API,然后我……这种刷网页流量的做法跟故意投不进球刷篮板的做法异曲同工之妙啊!

于是,简化API的数量就显得很有必要。如何实现?

我想到了一个动态API的设计方法,其实powerFloat等其他一些jQuery插件我或多或少用过类似处理,这里用得更明显,于是专门把这个概念提出来。

主要分为3个方面:

  1. 同一个API名称,在不同情境下的含义是不一样的。如container在Carousel效果中表示动画容器,在Tab效果中表示动作容器。
  2. 挖掘API的潜力,替代另一个API。

    例如:classAdd就可以判定indexSelected,因此,类似activeIndex参数就多余。

    以及根据autoTime时间值就可以确定是否要自动播放(0或其他),根本就不需要像switchable那样,需要autoplay(是否自动播放)和interval(自动播放时间间隔)两个参数。

  3. 自适应情境的API值。如”auto“,灵感来自CSS的属性值,例如overflow: auto.

powerSwitch总共就14个基本API(且大部分你无需关心),而kissy的switchable光自身就26个API,还不算Tabs, Slide, Carousel, Accordion等组件的API。

易用性可见一斑。

匿名API
这是自己另外提出的一个概念。其出发点有这么几个:

  1. 有些功能,用户很少使用,99%的用户使用默认的或使用基本API就好,我们默认这些API不暴露。就像装软件的高级选项,但高级用户依然可以使用。
  2. 有些功能,仅仅某一种效果才用到。你是一能,在万能插件中,似乎等级小了点,因此,默认匿了。也就是,只有多面手才能作为万能插件的API走上台面。

有人可能会疑问,为何API要进行分类,分基本和匿名?

答案很简单:更高的效益!

最近品大闸蟹的季节,可能都知道,大闸蟹的出售是分重量的,3两的,4两的,还有极品5两的,不同的两数价格倍数的差异,为的是更好的总售价。还有水果,例如苹果,枣子等都是这样,分上等品和一般品,上等品高价出售,一般品留给有需要的人。

API分类也有类似的好处,基本API让插件显得更简洁更上档次,匿名的API存在可以满足一些不常用的特殊需求。整理收益大大滴!

四、powerSwitch与GitHub

以前写的jQuery插件全部都要自己打包,上传,耗费自己的流量供自己下载。好累,能躺着决不坐着的我肯定是不爽这个的,于是,现在偷懒,把这次的项目放在了GitHub上,大家一起“哟哟,切克闹”!

项目GitHub地址:https://github.com/zhangxinxu/powerSwitch
github fork 或download

欢迎大家叉我或者下载。

五、powerSwitch概述

powerSwitch为一款依赖jQuery框架的jQuery插件,用来实现实际web开发中各种切换效果。

目前支持的效果有:

  • 选项卡
  • 可以自动播放的选项卡
  • 可以自动播放,可以前进后退且暂停的选项卡。
    播放以及可以暂停的选项卡 张鑫旭-鑫空间-鑫生活
  • Carousel跑马灯切换(边缘版)
  • Carousel跑马灯切换(无尽版)
  • Accordion手风琴效果
    手风琴效果截图
  • 更多展开收起
    展开更多效果
  • 可伸缩的导航
    可伸缩的导航
  • 文字广告播放
    文字广告播啊播
  • …等其他~

优点:

  • 万能
  • API简洁,仅14个,名称很普通,很好记
  • 小,gzip后只有3.2K
  • 兼容性好,兼容IE6+,使用jQuery 1.4以及以上版本
  • 超级灵活,DOM结构随心所定
  • 没有任何CSS依赖
  • 对锚点技术友好

不足:

  • touch事件尚未支持
  • 不支持动态委托
  • aria不内置
测试页面、demo页面、API文档

测试页面: /zhangxinxu/powerSwitch/master/index.html
demo页面: /zhangxinxu/powerSwitch/master/demo/_html/index.html
API文档: /zhangxinxu/powerSwitch/master/api/index.html

其中,测试页面为各种基本效果实现,有源代码使用的示意,上面效果的截图全部来自测试页面。

Demo页面为国内一些注重展示性网站主页面的重要的切换效果的实现,包括:迅雷动漫首页、淘宝网首页、京东商城首页、易迅网首页的各种切换效果。用来表明powerSwitch的实用性,以及确实对得起“万能”这个称号!
例如,易迅网高保真demo页面的截图:
易迅网的各种切换效果 张鑫旭-鑫空间-鑫生活

demo页面并没有直接的源代码展示,但是,您右键页面→查看页面源代码就可以看到HTML以及JS的使用了。HTML全部自己手动重写,很干净简洁,非常适合您的学习。

API页面就是专门介绍插件的基本API以及匿名API的,截图缩略图如下:
API文档页面的截图 张鑫旭-鑫空间-鑫生活

API文档页面中,点击左侧的API项,右侧切换的效果就是使用powerSwitch实现的。

本质上,powerSwitch是一个万能的切换引擎。

六、powerSwitch使用

前面提到,powerSwitch采用的是映射机制

映射机制
对于kissy的switchable,其选项卡和面板的关联采用的是限制DOM结构(容器→两子元素容器→子容器分别是选项卡列表和面板列表),以及API设置(如以下诸多API: navCls, contentCls, triggerCls, panelCls, triggers, panels)。

问题显而易见,牺牲了DOM的自由,或者牺牲了API的数量。

映射机制可以很好的修复此问题。

这其实是一种思维模式的转变。人总是习惯从日常事物映射到代码中,写一个插件,情感上类似抚养一个孩子,你可能要手把手教他,这是筷子,这是碗,你要用手拿筷子,然后夹碗里的肉肉,然后塞在自己的嘴巴里,然后吃下去。反映在插件上就是,有一个筷子API,有一个碗API,需要一个手API,有特定的限制,如肉要从碗到嘴。实际上,需要这么呵护吗?我们的最终目的是肉到肚子里,所以,我们其实并不要关心肉是如何进去的。你不能因为用筷子夹进去是最常用最靠谱的方法,就给他套上这么个框框,还自己觉得挺好。

如果我们纯粹从插件角度讲,需要的是更简单粗暴的方法。没有碗,没有筷子,你不用关心肉是在地上还是正在火上烤,你也不要担心不用筷子夹会不会烫着。你只要关心,“肉谁吃”这一个问题就可以了。

所以,我们只要设计这样一个插件:
1. 确定这块肉谁吃
2. “啪”塞他肚子里(切换)

就OK了!简单粗暴,但却最有效,没有碗、筷子这种限制。

如何确定肉该谁吃呢?可以采用映射机制,在肉上标记,(确定)是你吃呢,还是你们吃呢?这种好处在于,我想把肉喂给正在忍饥挨饿的非洲小盆友,也是可以的。直接肉上映射非洲小盆友,插件一调用,perfect done!

我突然想起了大学时候看过的一部电影,稍等,让我找找~~

哈~找到了,叫做《心灵传输者》。主角可以瞬间移动,只要知道目的地的位置路线即可,是不是非常类似于这里的映射。如果瞬间移动需要:你外面是个屋子(容器限制),你移动的地点外面也是个屋子。我想,主角早就被杀死了!

再扯点题外话,在我们每天挤地铁上下班的现实世界是没有瞬间移动这样的场景,So,我们在设计插件的时候,第一反应就不会是这种超自然的思维(思维的连贯性限制),而是自然世界的逻辑思维方式的呈现。代码它是很科幻的,瞬间移动正是其特点(速度快),我们要学会站在代码的角度想问题。您要是对这个话题感兴趣,可参见我之前的“关于一个JS功能实现的思维方式”一文。

具体的做法是使用一个自定义属性做映射。参考如下选项卡代码(就是demo页面中淘宝网那个示例,注意下HTML结构):

<div id="adSlideBox" class="tb_slide_box tb_slide_ad">
    <img id="adSlideImg1" src="1.png" class="tb_slide_img">
    <img id="adSlideImg2" data-src="2.jpg" class="tb_slide_img" style="display:none;">
    <img id="adSlideImg3" data-src="3.jpg" class="tb_slide_img" style="display:none;">
    <img id="adSlideImg4" data-src="4.jpg" class="tb_slide_img" style="display:none;">
    <img id="adSlideImg5" data-src="5.jpg" class="tb_slide_img" style="display:none;">
    <div id="adSlideBtn" class="tb_slide_btn">
    <!-- 这是点点 -->
        <a href="javascript:" class="tb_slide_on" data-rel="adSlideImg1"></a>
        <a href="javascript:" class="tb_slide_a" data-rel="adSlideImg2"></a>
        <a href="javascript:" class="tb_slide_a" data-rel="adSlideImg3"></a>
        <a href="javascript:" class="tb_slide_a" data-rel="adSlideImg4"></a>
        <a href="javascript:" class="tb_slide_a" data-rel="adSlideImg5"></a>
    </div>
</div>

可以看到,图片img标签直接暴露在外面,感觉就像把肉扔在了地上,而不是碗里,但又有什么关系呢?如果你喜欢,img标签甚至可以放在页面底部,body标签下。映射这种最直接粗暴的关系连接打破了层级、相邻关系等一系列的限制。

powerSwitch有个API名称为"attribute",就是表示自定义属性名称,默认是"data-rel",可以是id, class类名或者类似"#example p"的完整选择器,具体可参考API文档之attribute.

基本使用
很简单——

$(事件触发源).powerSwitch({ /* APIs */ });

powerSwitch的包装器对象为“事件触发源”,嘛意思?

哈,很简单,就是触发切换行为的元素们。
例如,选项卡效果就是这个:
选项卡效果

或者是其变体——点点点,或1~5数字按钮:
点点点

跑马灯效果就是上一项下一项按钮:
上一组下一组示意

或者是更多按钮:
展开更多效果

或者就是切换元素自身(映射到自己身上):
文字广告播啊播

然后被切换的面板或者列表等使用映射关联就可以了。

APIs们
基本的API见下表:

API名称 默认值 简单释义
direction "horizontal" 偏移动画的方向,默认水平,垂直方向为"vertical"
eventType "click" 事件类型。默认点击事件。"hover"表示鼠标经过触发。
classAdd "" 选项卡选中态添加的类名。
classRemove "" 选项卡选中态移除的类名。
classPrefix "" 按钮禁用,前进,后退,暂停,播放等的前缀。
attribute "data-rel" 完成映射的自定义属性。
animation "auto" 动画类型。默认"auto"表示,选项卡无效果,跑马灯偏移动画。
duration 250 动画持续的时间。
container null 容器。动态API,详见API文档
autoTime 0 自动播放时间,默认为0,表示不自动播放。其他合法数值,触发自动播放。
number "auto" 每次切换的数目。更多展开效果全部切换,其他效果默认为1个。
hoverDelay 200 鼠标事件经过触发源延时触发的时间,单位毫秒。
toggle false 是否展开后再次点击可以收起。默认false表示只能展开,二次点击不收起。
onSwitch $.noop 切换触发之时的回调方法。支持的参数为动态。具体参考API文档

上表只是简单介绍,具体使用以及一些匿名API的使用还需要参考API文档哦~

七、临门一脚,现身说法

API文档只是一个纵向的讲解。现在,还差以效果为主线的横向介绍了!

1. 选项卡效果
选项卡效果有两个专属API,classAddclassRemove,因为切换效果,Tab选项卡是大头。因此,这两个API绝对上得了台面。

都什么时候使用呢,看下面的说明:

  1. 假设4个选项卡,默认状态的类名是.default, 选中状态的类名是.default .active. 则classAdd的值就是active,而classRemove的值还是默认的空字符串''.
  2. 假设4个选项卡,默认状态的类名是.default, 选中状态的类名是.active. <则code>classAdd的值依旧是active. 而classRemove的值此时就是default.

看明白了没有,classAddclassRemove都是表示选项卡按钮在选中状态时候需要添加和移出的类名哦!

按照目前主流选项卡激活态实现的尿性,classRemove都是酱油命哦!

对了,classAdd实际上是个动态API,其还隐匿了一个匿名API,indexSelected. 因为,如果选项卡处于选择态,必然会有classAdd对应的类名,自然可以借此得知indexSelected值,因此,indexSelected就可以退居幕后,一些特殊场合出面就可以啦!

默认的选项卡是没有“上一项”、“下一项”切换按钮的,但是,您可能会发现,测试页面,以及demo页面中大量出现带翅膀的选项卡:
播放以及可以暂停的选项卡 张鑫旭-鑫空间-鑫生活

如何做到的?

基本APIs中有个container配置项,这是个具有代表性的动态API。在选项卡模式中(插件通过映射关系链判断),如果设置了container值,插件会在container元素后面append,“上一项”,“下一项”以及“播放|暂停”三个按钮。也就是我们看到的左右两边的小翅膀啦!按钮的命名规则API文档中有详细解释哦!

动态API创建操作按钮

2. 跑马灯效果
跑马灯效果是绑定在“上一组”、“下一组”这段小翅膀按钮上的。默认是左右有边界的,就是如果列表们偏移到边缘了,“下一组”或“上一组”按钮就会被禁用。插件会添加您指定的或自己决定的类名。

你可能会询问,demo中很多切换都是没有尽头的无限切换模式。如何设置的,似乎基本API中没有相关的配置项啊?

匿名API+动态API实现。匿名API中,有个API项为classDisabled,所有匿名API项默认都是不存在的,hasOwerPropertyfalse的,这样的设计可以区分是插件行为还是用户行为。

如果您对classDisabled置之不理或者设置了你自己想要的类名,很显然,您是认同的插件的行为:我会disabled你的按钮,当你不能再切换的时候。因为,如果是无限切换,按钮是不可能存在禁用状态的。

但是,如果您是设置了classDisabled'', nullfalse,插件就会明白,你不希望存在禁用的类名,也就是你希望可以无限切换。非常合情合理,您说是吧!

跑马灯效果如果是translate动画,有个必不可少的API项,container,没有这个,跑马灯的马根本就跑不起来。插件相当智能,您可以将container放在列表的父容器上,也可以放在定死高宽的容器上。因为默认animation值为auto(也是动态API),于是就有前者使用CSS3 transform移动,后者scroll值改变移动。但是,从实际效果来看,建议container表示前者,动画性能更出众。而后者250毫秒的动画表现得就像是500毫秒。

跑马灯效果还有一个动态API,number. 我发现很多跑马灯插件需要使用者指定容器的尺寸,当前显示的数目等。我有些不解,我只要知道每次要切换几个不就可以了。虽然会出现部分留白的情况(如遇到展示了5项,每次切换只移动1项的愚蠢设置),我觉得it’s ok, it’s no problem. 一直展示到最后一项。

number还可以控制“更多-展开|收起”效果对于列表每次显示的数目。

跑马灯效果还支持fade等动画效果。demo中易迅网的公告就是如此实现的,建议您留意下此效果中duration: "sync"的参数设置。此时,container配置项可以打酱油了!

3. 手风琴效果
手风琴效果本质上就是tab效果,不过也有不同,手风琴类似变体可以展开多个面板。借助toggle这个API就可以实现,您可能会疑问,toggle表示能伸能缩,multiple才是表示可以多个面板同时出现吧~

一瞬间想来似乎是那么回事,但是,静下心来,稍微一琢磨就就会发现,如果一个选项面板能伸能缩,其毕竟支持同时展开多个面板。

从这一点看来,toggle实际上也是和动态API,完全取代了multiple. 同时也适用于“更多-展开|收起”这种交互效果。

4. “更多-展开|收起”效果
只要一个设置,toggletrue就可以了。啦啦啦啦啦~~

5. 文字广告无限播
您会发现,这种效果根本就没有事件触发源,如何绑定powerSwitch呢?

绑定自身就可以了!

如下代码示意:

<ul id="wordSlide" class="word_slide" data-rel="#wordSlide li">
    <li id="wordList1" style="display: list-item;" data-rel="wordList1"><a href="##">广播信息1</a></li>
    <li id="wordList2" data-rel="wordList2"><a href="##">广播信息2</a></li>
    <li id="wordList3" data-rel="wordList3"><a href="##">广播信息3</a></li>
</ul>

以上为5大基本效果,over~~~祝你好运!

八、结束语

还是那句话,有时候,自我感觉良好的东西别人看来并不怎么样。虽然说自己觉得这个插件可以说是今年下半年个人代表作之一,但别人可能觉得不过尔尔。So,谦逊的心态需要永远保持,也很重要。

现在powerSwitch已经开源到GitHub上了,一些问题反馈也更方便了。So,如果有幸承蒙您试用该插件,发现任何问题,或者觉得可以改进的地方。欢迎不息笔墨指正、提点。

如果您有任何的疑问,或者觉得不太好实现的切换效果,您可以留下评论,或邮件(zhangxinxu@zhangxinxu.com)联系,只要问题不是很怪异,我都会及时回复的。

powerSwitch走的解释性语言路线,NO模块化,NO“高端”的面向对象。一个不限制UI,不限制HTML的万能切换引擎。本插件适合有一定CSS以及HTML基础的人,且面向实际开发制作,没有华而不实的效果,实用简单,性能高效。希望本插件能够大大简化您开发制作的成本,人人都能在上班的时候哼哼小曲把把妹,泡泡咖啡咪咪睡。

哈,未来要增加touch事件,增强对移动端的支持。

就这些,祝女士们双十一购物快乐;男士们双十一能够快乐!

(本篇完)

分享到:


发表评论(目前85 条评论)

  1. 夏天说道:

    要是早看到这篇文章脱离苦海了

  2. 不太万能说道:

    之前的powerFloat插件 有个特大的漏洞啊 没看到怎么移除这个提示的方法 只有添加 我现在下拉显示一次之后 以悬浮就提示