最近项目上要在浏览器端实现一个类似 Linux 下 ls
命令的显示效果。虽然实现过程没花多长时间,但是觉得这个效果还挺赞的,所以分享一下。
神奇的ls命令
ls命令对于前端同学可能比较陌生,简单来说就是Linux终端中的一个常用功能,用来显示某个目录下的文件(夹)列表。不过这它的功能不是本文讨论的重点。重点是它神奇的显示效果,比如下面这样:
看似并无神奇之处,就是文件(夹)名称逐行显示而已,别急,再来看下面两张截图:
不知道你现在有没有发现布局发生了变化:由最初的1列变成了多列!
你很容易想到列数量会随着窗口的宽度而改变,这种猜测是对的,但并不全面,因为决定其显示排列的还有文件(夹)名本身的长度。比如我再指定目录执行一条 ls
命令进行对比:
两条命令执行时窗口宽度是一样的,但是在长文件(夹)名的情况下是3列,而短文件(夹)下是4列。
ok~了解完ls
命令的显示特点之后问题来了,我们该怎么实现呢?
实现难点与解决方案
更多文章请关注公众号“Web学习社”。
这种列数发生变化的情况在网站页面中并不少见,你可能第一个就会想到媒体查询或者Bootstrap。但很遗憾事情并没有这么简单。媒体查询和Bootstrap都是针对不同屏幕宽度进行的自适应,而并不会根据内容自动调整,无法满足我们的要求。
似乎浮动可以根据内容大小来进行自动排列,但和我们的需求相比也有一个很大的差别。那就是ls
命令在调整好合适的列数之后,每列文件(夹)名都是等宽左对齐的。而使用浮动后的效果是每行长的名称排列少,短的名称排列多,造成列数不统一,参差不齐。
到此看似毫无头绪,不过可以参考“把大象放进冰箱里”分几步的例子,分步骤来解决这个问题。这个问题我们其实可以分两步进行分析:
- 显示的列数需要根据窗口大小和名称长度两者共同决定,按照已知的使用css的方式无法解决。那么我们只能用最笨的方式进行动态计算。
- 列数确定以后要确保每列等宽等间距,且左对齐,这个比较容易实现,可以设置等宽等间距。
按照这个思路我们来实现第1步,那就是怎么计算出合适的列数。看看列数是由哪些因素决定的:
- 窗口的宽度。
- 名称的长度。
- 名称之间的横向间距。
窗口的宽度可以通过dom获取或者样式设定,名称宽度可以通过fontSize进行计算,一般一个中文字符宽度为一个fontSize值,而英文数字则为一半,这里我们为了方便计算,只考虑英文和数字的情况。横向间距则可以由样式设定。那么可以得出计算公式:
窗口宽度 >= 列数 * (名称长度 * fontSize/2 + 间距)
这个不等式并不准确,因为当列数等于1的时候是最有可能满足这个不等式的,但显然不是我们想要的结果,所以还要加上另一个不等式:
窗口宽度 < (列数 + 1) * (名称长度 * fontSize/2 + 间距)
满足这两个条件的列数才是我们的最优解。不等式右边的表达式实际上就是行宽,更准确的说是每一行的行宽。当然这个表达式其实也不严谨,更严谨的是下面这样:
|
|
代码如下:
|
|
有了上面的不等式,那么现在我们就可以开始逐行计算了,不过我们从分几列开始算起?如果从分1列的方式算起,那么大多数情况下前面的分列方式都不是最优解,所以我们考虑直接从最优解算起,找到最长的名称和最短的名称并假设它们在一列,如果不满足则减少一列。
|
|
至此,我们就完成了第1步。第2步这种布局方式其实很常见,其实就是古老的table布局,那么我们渲染到页面的时候直接使用table来实现。
|
|
具体代码:
http://jsbin.com/zipabig/1/edit?html,css,js,output
一部由众多技术专家推荐, 帮你成为具有全面能力和全局视野工程师的进阶利器—— 《了不起的JavaScript工程师》出版了! 点击下方链接即刻踏上进阶之路!
- 淘宝:https://detail.tmall.com/item.htm?id=600756390664
- 京东:https://item.jd.com/12562349.html?dist=jd
- 当当:http://product.dangdang.com/27922044.html