如何实现像500px.com这样的图片排版效果呢? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xingzhi
V2EX    问与答

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

  •  
  •   xingzhi 2012-11-19 23:38:59 +08:00 7013 次点击
    这是一个创建于 4787 天前的主题,其中的信息可能已经有所发展或是发生改变。
    每次刷新, 图片的尺寸,以及图片的排版都会有变化。但总可以不留空地填满页面。

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

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

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

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

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

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

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

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

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

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

    因此, 填充时,要根据图片的数量与尺寸进行排版, 实现全填充页面。
    omg 头都大了。
    august
        10
    august  
       2012-11-20 11:16:02 +08:00   1
    @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
        11
    august  
       2012-11-20 11:16:55 +08:00
    每 preview_block 要先css定好width height relative 然後 img absolute
    loading
        12
    loading  
       2012-11-20 11:17:33 +08:00
    这不就是瀑布吗
    xingzhi
        13
    xingzhi  
    OP
       2012-11-20 11:32:26 +08:00
    @august 谢谢。 我会先写着试试:)
    momou
        14
    momou  
       2012-11-20 12:08:43 +08:00


    它这个根本没考虑图片大小的问题,指定图框高度为441px按比例缩放,然后布局几种不同的形式变换
    sinreal
        15
    sinreal  
       2012-11-20 17:45:51 +08:00
    感谢这个有趣的讨论。
    javaluo
        16
    javaluo  
       2012-11-20 18:45:54 +08:00
    先等比等宽缩放4个格式,然后css控制就完事了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3054 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 00:41 PVG 08:41 LAX 16:41 JFK 19:41
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86