2012-9-19 蓝蓝设计的小编
转载蓝蓝设计( www.lanlanwork.com )是一家专注而深入的设计机构 ,为期望卓越的国内外企业提供有效的 BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务
来源:http://www.uisheji.com/114057.html
如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里
从事网页重构好几年了,Javascript能力一直比较菜,主要还是做得太少。为了提高这方面的能力,这段时间主动承担了一些这方面的工作,真心感到学习和积累的不易,不过时常伴随着一些解决问题之后的小小成就感又让人乐此不疲。
在近期一个项目中,遇到一个图片列表自适应宽度显示的问题,需求本身并不难,借此且算是梳理和总结一下当时的解决思路吧,也期望能给有需要做这类需求而又知如何下手的同学带来一点小启发。实现的方法应该很多,如果你有更好的,要分享哦~~
需求是这样的,在一个自适应宽度的栏目里(如图1):
1、 栏目的宽度可以因用户的操作发生改变,如拖拽改变窗口大小等;
2、 当宽度改变之后,需要图片列表总是能在栏目中完好地显示:图片之间有一定的间距,并且不会出现半张图。
3、 若当前宽度不能完全显示所有图片时,可以通过点击左右两边的箭头进行滚动显示。如图2:
经过分析我们可以把需求分解为:栏目的宽度自适应、图片列表的自适应显示、列表的左右滚动。栏目的宽度自适应,可以直接用样式来解决,宽度的获取也简单,不再多说。图片的滚动也还好说,无非就是通过样式改变列表的左右位置来实现。难点在于,在一个宽度会各种变化的区域中,怎么让图片列表自适应显示呢?
对比图1、图2,我们发现前后的变化有:栏目宽度、图片显示个数、图片之间的间距。宽度自适应好办,那图片个数和间距呢?嗯哪,这就是我们需要解决的核心问题。
1、关于可视区域
再看图2,栏目中只有3个图片,我们知道是因为其它部分被样式隐藏了,而整个图片列表其实是一直存在的一个整体。就像Flash里的遮罩一样,我们要做的其实是按照用户的意愿控制图片列表的某一部分显示给用户看到。为便于后面好讲,我们把用户可以看到的这部分列表区域称为列表的可视区域 。它的特点是随着当前栏目的宽度变化而变化,如图3:
图片列表是死的,栏目宽度是变化的,如何让图片列表适应栏目宽度的变化完好显示在可视区域里呢?好吧,你已经想到了…答案就是通过改变图片之间的间距来实现。如图4:
那么我们可以得出:
可视区域的宽度
= 可视区域内可显示的图片宽度总和(下文称可视图片数
) + 图片间距
总和
2、计算可视图片数
事情的关键是显示图片,我们就从计算可视图片数开始。可视区域的宽度我们可以轻易获取,所有图片的宽度也是统一的尺寸(什么?不统一?还好还好,我们这的产品经理倒是还没有BT到这个地步呢^^~ 这里还是先讲固定的情况吧,不固定的情况下回再探讨)。先忽略一下图片间距,那么问题可以简化为:
可视图片数 = 可视区域宽度 / 单位图片宽度
代码(代码中涉及到的html代码请查看下文Demo):
//获取当前可视区域的宽度 var pLstWrpWth = $('.jQ_ptLst').width(); //获取单位图片宽度(图片可能包括边框样式等,取列表元素Li的宽度参与计算以避免误差) var valLstLiWth = $('.jQ_ptLst li').width(); //计算当前可视图片数(可视区域宽度 / 单位图片宽度 再取整) valImgLth = Math.floor(pLstWrpWth / valLstLiWth);
3、计算图片间距
那间距怎么计算呢?从图4我们可以看出,除去所有可视图片的宽度剩下的就是间距的总和。于是:
间距总和 = 可视区域宽度 – 单位图片宽度 * 可视图片数
这样我们就可以计算图片间距了:
图片间距 = 间距总和(除去可视图片宽度的可视区域宽度) / 间距个数(即可视图片数+1,为何+1?看图4)
代码:
//向上取整可避免小数带来的误差) valpLstMg = Math.ceil((pLstWrpWth - valImgLth * valLstLiWth) / (valImgLth + 1));
到这里,你会发现,其实最终需要解决的问题就是计算图片间距。有了间距,我们就已经能做到根据栏目宽度,完好显示可视区域的图片了。至于能显示多少图,此时我们已经不关心了。
4、需要注意的情况
当上面计算出来的间距总和很小,或者干脆为0了… 如图5:
像基友一样合在一起显然不好看~ – 此时,我们可以设定一个最小间距来解决这个问题。当计算出的间距小于这个间距时,就减少1个可视图片,把原本属于这个图片的宽度分配给其余的图片作为间距。代码:
var pLstLesMg = 5; //设定最小间距,即临界间距 if(valpLstMg < pLstLesMg){ valImgLth = valImgLth - 1; //当间距小于临界间距时,可视图片数-1 fnpLstMg(); //重新计算可视图片数-1之后的间距 };
还有一种情况,如图6:
当可视图片数 大于列表总图片数 时(还有等于的情况哦),图片总数即为可视图片数。代码:
var pLstImgLth = $('.jQ_ptLst').find('img').length; //获取图片总数 if(valImgLth >= pLstImgLth){ valImgLth = pLstImgLth; //图片总数即为可视图片数 fnpLstMg(); //用新可视图片数重新计算间距 $('.jQ_plstRoRt').hide();//隐藏向右滚动箭头(初始化时可默认左箭头隐藏,右箭头显示) };
到这里,基本上图片列表自适应宽度显示就解决了,接下来就是图片列表的滚动问题。
5、列表滚动
有经验的同学可能一下就想到了,问题的关键是要怎么判断当前滚动的是否为最后一张图片(啊?你是说做循环滚动?滚到最后一张无缝拼接第一张图,如此永远滚下去?其实,我只是想说,你们的产品经理心眼真好~ 嗯好吧,看在大家都不容易的份上,我们姑且还是探讨一下这种情况吧)。
那么如何知道滚到最后一张图片了呢?我想的办法是通过宽度计算,即:
当已滚动总宽度
等于非可视区域宽度
(即可视区域两侧的宽度之和)时,即不能再向右滚动了。如图7:
代码:
var ptLstCurMg = parseInt(pLstRoWrp.css('margin-left')); //获取当前已滚动宽度 //当已滚动宽度 = 非可视区宽度,即已滚动至最后一图 var ptLstRoWth = (pLstImgLth - valImgLth) * (ptLstImgMg + valLstLiWth); if(ptLstCurMg + ptLstRoWth == 0){ $this.hide(); //隐藏右箭头 };
以上是向右滚的情况,向左滚时就简单了。当已滚动宽度为0时,即是向左滚动到头了。
//当已滚动宽度 = 0,即已滚动至最前一图 if(ptLstCurMg == 0){ $this.hide(); //隐藏左箭头 };
6、绑定方法
图片列表滚动讲完了,接下来就是执行这些方法了。为了自适应用户适时改变窗口大小的情况,需要将自适应函数绑定到resize方法中执行,代码:
//一旦窗口大小发生变化即会执行 $(window).resize(function(){ fnAutoWth(); //自适应方法 });
啰嗦这么多,其实主要围绕两个问题:
a. 通过计算图片间距控制列表的显示
b. 通过宽度计算解决滚动至最末
OK~点击这里是DEMO …(用浏览器打开之后,通过改变窗口大小,体验图片列表自适应效果。)
小思考 (没看DEMO的同学可以不用思考哦~):将DEMO用浏览器打开后,拖动窗口至最小宽度,即当前栏目宽度小于图片宽度时(小不动?用Chrome试试),列表中看不到图了,为什么?如何解决呢?
整个过程其实还是挺简单的,不知道我有没说清楚,大家有没听明白?如果没说清楚的地方正好你又感兴趣,可以留言哦~亲。不过,如果您是个修为高深的化神期强者,也希望多多指出不当之处啊,感谢感谢~~小可尚徘徊于筑基期~露怯…..学好JS说了好多年,想想那些年……所以,朋友,如果你也是个网页重构,别光写DIV了,有空多学学写写JS吧,挺有意思的呢~
话说,互联网发展日新月异,各种新技术层不出穷,需要学习的东西还真多呢。。。加油~
各种学压力大呀~ 要不,放松一下先撸一把?好吧… 小明、小纯 艾欧尼亚,搞起~~~
(转载请注明出处GDC)