V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
xingzhi
V2EX  ›  问与答

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

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

    页面上的图片共有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  
       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  
       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   ·   我们的愿景   ·   实用小工具   ·   2225 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 05:29 · PVG 13:29 · LAX 22:29 · JFK 01:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.