如何实现像500px.com这样的图片排版效果呢?

2012-11-19 23:38:59 +08:00
 xingzhi
每次刷新, 图片的尺寸,以及图片的排版都会有变化。但总可以不留空地填满页面。

页面上的图片共有4种尺寸, 那我在上传每张图片时,可以同时上传或直接剪裁出4种固定尺寸的图片。然后显示时,为图片随机选择一种尺寸。

主要问题在于, 如何根据图片的尺寸来做到不同的排版呢?

有点像瀑布流的形式,但瀑布流的图片宽度是固定了的,就是浮动布局, 在前端比较容易实现。

而这个网站明显有所区别, 这样的布局, 该如何实现呢?

谢谢。
6483 次点击
所在节点    问与答
16 条回复
alexrezit
2012-11-19 23:42:32 +08:00
你没发现那个网站上的图片都不是完整大小的么?
只是四列的网格, 然后图片按某种标准 (比如 popularity) 进行 aspect fill 而已.
xingzhi
2012-11-19 23:45:41 +08:00
@alexrezit
是的, 图片都不是完整大小,仅是一部分。 这个不难搞。

我就是没搞懂如何填充的这个算法。

请问什么是aspect fill, 我google下都是ios开发的东西。
alexrezit
2012-11-19 23:56:28 +08:00
@xingzhi 就是保持 aspect 不变, 然后填满指定的空间. 你用 iOS 自带的播放器看视频就知道了, 上下有黑边的是 aspect fit, 放大了之后没黑边左右两边截掉的就是 aspect fill.
qiayue
2012-11-20 00:27:05 +08:00
实现过类似的布局,不过我的算法弄得比较复杂。
你想象有很多2*2、2*1和1*1大小(嫌麻烦,去掉了1*2这种情况)的地砖,然后你要在一条宽为4,高不限的区域把地砖无缝铺下去。
你随手拿一块转,扫一眼区域,看最近的可以放下这块砖的位置在哪里,放下去。
重复上一步,知道所有的砖都铺下去了。
再次扫描整个区域,看哪里空着,从最后的位置找比空位置大或者相等的砖,把砖切小后放入空位置。
完成。
xingzhi
2012-11-20 00:33:09 +08:00
@alexrezit 貌似我说的和你说的不是同一码事。

---

目前找到了这个js库:
http://masonry.desandro.com/index.html
可以自动填充页面, 但对于同一高度的处理貌似还有问题。

这是同样的问题:
http://stackoverflow.com/questions/11413108/masonry-jquery-not-satisfy-with-the-results


这个问题还引发了更有趣的讨论:
http://stackoverflow.com/questions/11278754/how-to-implement-a-gapless-block-layout-algorithm

最后,发现涉及到Bin packing这个算法问题。
http://en.wikipedia.org/wiki/Bin_packing_problem

以上是我目前掌握的资料。
有兴趣的同学可以一看。 或给我些建议或资料:)
xingzhi
2012-11-20 00:43:09 +08:00
@qiayue
非常感谢, 是的, 我之前也曾如你这样想, 用递归的思想把剩余的不断填充。

但会有一个问题, 就是当高度不限时, 无法保证左右图片的高度一致。
请看图:
qiayue
2012-11-20 10:49:39 +08:00
@xingzhi 对,在放砖的时候还需要一个高度修正,有些情况,有些位置只能放置1高度砖块,我程序里是有写的,上一个回复里没写。
august
2012-11-20 10:53:05 +08:00
我最近在寫一個頁面也是模仿 500px 的,用js來控制顯示圖片 absolute 定位
xingzhi
2012-11-20 11:14:11 +08:00
@qiayue
恩,好的,我明白了。
不知道你方不方便把相关代码发给我学习下呢?
lvyaojia#a#gmail.com
非常感谢。

@august 是自己写js么,还是用js库?

我要实现的页面有一个难点就是:
1. 图片尺寸不固定——每张图在后台随机选择尺寸。
2. 图片数量有限, 并非像瀑布流般无限填充。

因此, 填充时,要根据图片的数量与尺寸进行排版, 实现全填充页面。
omg 头都大了。
august
2012-11-20 11:16:02 +08:00
@xingzhi 自己寫的js 就一個function 貼出來給你看看有沒有用。

function photo_offset_position() {
$('div.preview_block').each(function() {
var div = $(this);
var divRatio = div.width() / div.height();
var img = $('img', this);
var imgRatio = img.width() / img.height();

if (divRatio == 1) {
if (imgRatio > 1) {
img.css('height', div.height());
var offsetX = (img.width() - div.width()) / 2;
if (offsetX > 0)
img.css('left', -1 * offsetX + 'px');
}
else if (imgRatio < 1) {
img.css('width', div.width());
var offsetY;
if (img.height() / 2 >= div.height())
offsetY = img.height() / 2 - div.height();
else
offsetY = (img.height() - div.height()) / 2;
img.css('top', -1 * offsetY + 'px');
}
else {
img.css('height', div.height());
}
}
else {
if (divRatio < imgRatio) {
img.css('height', div.height());
var offsetX = (img.width() - div.width()) / 2;
if (offsetX > 0)
img.css('left', -1 * offsetX + 'px');
}
else if (divRatio > imgRatio) {
img.css('width', div.width());
img.css('left', 0);
var offsetY;
if (img.height() / 2 >= div.height())
offsetY = img.height() / 2 - div.height();
else
offsetY = (img.height() - div.height()) / 2;
img.css('top', -1 * offsetY + 'px');
}
else {
img.css('height', div.height());
}
}
});

}

沒有注釋的好習慣-- 將就著看吧
august
2012-11-20 11:16:55 +08:00
每個 preview_block 要先css定好width height relative 然後 img absolute
loading
2012-11-20 11:17:33 +08:00
这不就是瀑布吗
xingzhi
2012-11-20 11:32:26 +08:00
@august 谢谢。 我会先写着试试:)
momou
2012-11-20 12:08:43 +08:00


它这个根本没考虑图片大小的问题,指定图框高度为441px按比例缩放,然后布局几种不同的形式变换
sinreal
2012-11-20 17:45:51 +08:00
感谢这个有趣的讨论。
javaluo
2012-11-20 18:45:54 +08:00
先等比等宽缩放4个格式,然后css控制就完事了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/52808

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX