领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

继承Jquery的方法--tab滑动动画切换

nixiaole 2024-12-03 17:11:26 知识剖析 15 ℃


前言

最近产品有个需求,要做个tab标签切换,这最基本的样式当然不在话下,但作为极客的我总要与众不同吧!于是大开脑洞,也就想出了个tab切换时候加个滑动动画(表笑我,谁让咱没达到UI交互设计师的高度呢),再然后正好想起本站曾经有个效果(传送门),于是乎找了这个效果demo给产品看,产品欣然同意了。

那么,问题又来了,之前的这个效果有几个弊端,也是我和产品认为不好的:

  1. 不同tab页的内容高度不同,差距可能还比较大,不能用一个统一的固定高度来搞

  2. 例如从tab1跳到tab3这种跨项的情况,原则上是不能让用户在动画过程中看到tab2内容的(不要问为什么,这就是极客精神),如果从tab1跳到tab5,中间跨了3项,这体验总感觉略low啊

因此,轮子还得造!

需求功能

  1. 不固定高度。高度不同的tab页直接也可以自适应切换

  2. 跨项无缝切换。跨项切换时候不会看到中间项内容

  3. tab标题也增加滑动动画

思路分析

  1. 所谓不固定高度,那么只有在即将动画时拿到切换前和切换后两个tab页中较大的高度进行设置

  2. 跨项不显示中间项的话,那么只有“造假”了:把切换前和切换后的两个tab页克隆下来构造个动画区,放到最前面,走个过场动画,同时隐藏掉原来真实tab页,结束后remove掉动画区,同时将真实tab页展现(本人觉得这是个简单的笨办法,如果大神有更合适的思路可以留言讨论)

代码赏析

以下是jquery插件的原代码,注释可以说的手把手的教学!每一步都写了注释,重点就是看“tab页动画部分”的注释

$.fn.extend({tab: function (index) {//index:初始化后第几个tab显示,默认0 ? ?this.each(function () { ? ? ?var animating = false;//动画进行中的标识,保证不会在动画过程中再次执行动画 ? ? ?var $this = $(this); ? ? ?var $tabCard = $this.children(".tab-card"); ? ? ?var $tabCards = $tabCard.children(); ? ? ?var $tabPaper = $this.children(".tab-paper"); ? ? ?var $tabPapers = $tabPaper.children(); ? ? ?var curIndex = $tabCards.filter(".cur").index();//通过cur获取当前tab页序号 ? ? ?curIndex = index || (curIndex == -1 ? 0 : curIndex) || 0;//参数index优先级最高 ? ? ?//初始化cur状态 ? ? ?$tabCards.removeClass("cur"); ? ? ?$tabPapers.removeClass("cur"); ? ? ?$tabCards.eq(curIndex).addClass("cur"); ? ? ?$tabPapers.eq(curIndex).addClass("cur"); ? ? ?/*************************tab标签的动画部分*************************/ ? ? ?/*此段代码借鉴lavaLamp,构造一个绝对定位的back li在滑动*/ ? ? ?$tabCard.each(function () { ? ? ? ?var b = $(this), noop = function () { ? ? ? ?}, $back = $('<li class="back"><div class="left"></div></li>').appendTo(b), $li = $("li", this), curr = $("li.cur", this)[0] || $($li[0]).addClass("cur")[0]; ? ? ? ?$li.not(".back").hover(function () { ? ? ? ? ?move(this) ? ? ? ?}, noop); ? ? ? ?$(this).hover(noop, function () { ? ? ? ? ?move(curr) ? ? ? ?}); ? ? ? ?$li.not(".back").click(function (e) { ? ? ? ? ?if (!animating) { ? ? ? ? ? ?setCurr(this); ? ? ? ? ?} ? ? ? ?}); ? ? ? ?setCurr(curr); ? ? ? ?function setCurr(a) { ? ? ? ? ?$back.css({"left": a.offsetLeft + "px", "width": a.offsetWidth + "px"}); ? ? ? ? ?curr = a ? ? ? ?} ? ? ? ?function move(a) { ? ? ? ? ?$back.each(function () { ? ? ? ? ? ?$(this).dequeue() ? ? ? ? ?}).animate({width: a.offsetWidth, left: a.offsetLeft}, 500, "easeOutBack"); ? ? ? ?} ? ? ?}); ? ? ?/*************************tab页动画部分*************************/ ? ? ?/*tab标签点击*/ ? ? ?$tabCards.on("click", function () { ? ? ? ?slide(this) ? ? ?}); ? ? ?/*直接更改当前tab标签样式*/ ? ? ?function changeCard(the) { ? ? ? ?var $t = $(the); ? ? ? ?$t.addClass("cur").siblings().removeClass("cur"); ? ? ?} ? ? ?/*直接切换tab页内容位置*/ ? ? ?function changePaper(the) { ? ? ? ?var $t = $(the); ? ? ? ?var ci = $t.index(); ? ? ? ?$tabPapers.eq(ci).addClass("cur").siblings().removeClass("cur"); ? ? ? ?curIndex = ci; ? ? ? ?$tabPaper.height($tabPapers.eq(ci).height()); ? ? ?} ? ? ?/*tab页滑动动画*/ ? ? ?function slide(the) { ? ? ? ?if (!animating) { ? ? ? ? ?var $t = $(the); ? ? ? ? ?changeCard(the); ? ? ? ? ?var ci = $t.index(); ? ? ? ? ?// 当前页和切换页相同时 直接返回 ? ? ? ? ?if (ci == curIndex) return; ? ? ? ? ?var $fromPaper = $tabPapers.eq(curIndex); ? ? ? ? ?var $toPaper = $tabPapers.eq(ci); ? ? ? ? ?//克隆一个当前页和一个切换页,后续只做动画使用 ? ? ? ? ?var $fromPaper_clone = $fromPaper.clone(); ? ? ? ? ?var $toPaper_clone = $toPaper.clone(); ? ? ? ? ?//获取tab页宽度,padding样式 ? ? ? ? ?var paperWidth = $tabPaper.width(); ? ? ? ? ?var paperPadding = $tabPaper.css("padding"); ? ? ? ? ?var paperPaddingLeft = parseInt($tabPaper.css("padding-left")); ? ? ? ? ?//通过宽度和padding计算总宽度 ? ? ? ? ?var paperWidthTotal = paperWidth + 2 * paperPaddingLeft; ? ? ? ? ?//比较当前页和切换页的高度,选取高的作为动画时的高度 ? ? ? ? ?var paperHeight = Math.max($fromPaper.height(), $toPaper.height()); ? ? ? ? ?//定义动画区样式 ? ? ? ? ?$fromPaper_clone.css({ ? ? ? ? ? ?float: "left", ? ? ? ? ? ?display: "block", ? ? ? ? ? ?background: "#fff", ? ? ? ? ? ?padding: paperPadding, ? ? ? ? ? ?width: paperWidth, ? ? ? ? ? ?height: $fromPaper.height() ? ? ? ? ?}); ? ? ? ? ?$toPaper_clone.css({ ? ? ? ? ? ?float: "left", ? ? ? ? ? ?"display": "block", ? ? ? ? ? ?background: "#fff", ? ? ? ? ? ?padding: paperPadding, ? ? ? ? ? ?"width": paperWidth, ? ? ? ? ? ?height: $toPaper.height() ? ? ? ? ?}); ? ? ? ? ?//定义动画区,此动画区只作动画使用,动画完成后立刻remove ? ? ? ? ?var $animateArea = $("<div></div>"); ? ? ? ? ?$animateArea.css({ ? ? ? ? ? ?"position": "absolute", ? ? ? ? ? ?"top": 0, ? ? ? ? ? ?left: 0, ? ? ? ? ? ?width: 2 * paperWidthTotal, ? ? ? ? ? ?height: paperHeight ? ? ? ? ?}); ? ? ? ? ?//定义动画到达的位置,比较切换页和当前页序号大小,以此决定动画是向前滑动还是向后滑动 ? ? ? ? ?var animateLeft; ? ? ? ? ?if (ci > curIndex) { ? ? ? ? ? ?$animateArea.css("left", 0).append($fromPaper_clone).append($toPaper_clone); ? ? ? ? ? ?animateLeft = -paperWidthTotal; ? ? ? ? ?} else if (ci < curIndex) { ? ? ? ? ? ?$animateArea.css("left", -paperWidthTotal).append($toPaper_clone).append($fromPaper_clone); ? ? ? ? ? ?animateLeft = 0; ? ? ? ? ?} ? ? ? ? ?//动画区被加载,同时tab页高度改变,真实tab透明隐藏 ? ? ? ? ?$tabPaper.append($animateArea); ? ? ? ? ?$tabPaper.height(paperHeight); ? ? ? ? ?$tabPapers.css({"opacity": 0, filter: "alpha(opacity=0)"}); ? ? ? ? ?//执行动画,动画结束后remove掉动画区,直接定位并显示出真实tab页内容 ? ? ? ? ?animating = true; ? ? ? ? ?$animateArea.animate({left: animateLeft}, 500, "easeOutQuint", function () { ? ? ? ? ? ?$animateArea.remove(); ? ? ? ? ? ?changePaper(the); ? ? ? ? ? ?$tabPapers.css({"opacity": 1, filter: "alpha(opacity=100)"}); ? ? ? ? ? ?animating = false; ? ? ? ? ?}); ? ? ? ?} ? ? ?} ? ?}); ?}});

效果预览~~

在线代码调试:地址

查看完整代码及详细内容:http://www.gbtags.com/gb/share/5781.htm

Tags:

最近发表
标签列表