工作项目中需要制作个Mobile上的Web App的展示,方便快捷访问和评价反馈。在展示页面能看到应用展示图,点击进入Web应用。我不是前端开发者,对HTML, CSS, JS这三剑客仅仅是略知一二。于是先规划了个简单的设计,感觉瀑布流的图片展示方式比较美观,同时布局的高度也一定灵活性。就按照Pinterest Android/IOS和花瓣Mobile Web App的目标开始实现。

第一天的成果是完成了基本的展示和链接。在iPhone模拟器上效果如下

玩转Masonry JS库来实现瀑布流Web效果

HTML页面代码snippet:

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
<!DOCTYPE html>
>
>
>
<!-- ... -->
 
<!-- Masonry JS library引入 -->
></script>
</head>
 
<body>
<!-- ... -->
 
<!-- Masonry在HTML里的初始化方法 -->
>
>
>
>
>
</a>
</div>
<!-- ... -->
</body>
></script>
></script>
></script>
></script>
 来自CODE的代码片
lightshow.html

 

相对应的CSS,比较关键的width的值,它决定了horizontal的column数目,比如这里的45%, 略小于50%, 也就是横向上可容纳两列:

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
,
{
/* juse a lil under 47 */
;
/*float: middle ;*/
;
);
);
);
}
 来自CODE的代码片
lightshow.css

 

这时有个layout问题会随机出现,纵向的layout有时会让每个展示层叠在一起。就像下面的这样:

玩转Masonry JS库来实现瀑布流Web效果

纵向的layout问题在第一次访问的时候比较容易出现,之后如果刷新一两次一般就恢复正常了。

原因来自于图片的<img>元素并没有指定的height。我们希望瀑布流的各个高度能够灵活展示,并由浏览器的布局计算得出。但是浏览器加载图片与layout计算的异步操作令这里留下了出错的可能。也就是说,图片必须先load完成之后,浏览器才能根据图片的natural size得出为这个<img>留下的layout的高度。而load图片的时间晚于layout计算就出现了这样的问题,浏览器以default的height来做布局。

W3School上的文档对<img>元素的width, height有这样的说明,建议尽量指定width, height。http://www.w3school.com.cn/HTML5/att_img_width.asp 。 但是像其它任何编程中一样,hard code带来的并不是最好的解决方法。有没有让我们灵活的计算<img>的height属性,并控制layout的方法呢?

请教了前端工程师朋友,找到了Masonry库的layout和sizing的方法,以及如何取得masonry instance的方法。

这样,解决方法是在<img>的onload()事件中调用masonry的layout()方法。这里注意的是masonry的instance是通过Masonry.data()这个方法取得的。data()这个方法是Masonry的,而不是masonry instance的方法。 代码如下:(官方文档 http://masonry.desandro.com/methods.html。)

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
>
(){
);
){
// 取得masonry的HTML element
);
// 获得masonry instance
);
// 在<img>的onload()中执行layout()
(){
();
}
}
});
/script>
 来自CODE的代码片
lightshow_layout.js

 

问题解决!!

 

 

Good staff is as follows, when the page finishes loading, masonry failure and I do not know why, but I found a method that is masonry.reload.

This method works sometimes, I wonder why.

var $container = $('.container');
$container.masonry({    
        itemSelector: '.item',
        columnWidth: 25

}).imagesLoaded(function(){
    $container.masonry('reload');   
});
share
 
add a comment

2 Answers

In the newer versions of masonry you use "reloadItems" instead of "reload". I ran across a tip on this thread that pointed me in the right direction.

.imagesLoaded(function(){
      $container.masonry('reloadItems');   
      $container.masonry('layout');
});

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-10-17
  • 2021-11-14
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2021-10-27
  • 2021-05-10
  • 2022-12-23
  • 2022-12-23
  • 2021-07-26
相关资源
相似解决方案