5

I am trying to implement the md-grid-list in a masonry style but I seem to be stuck with having to decide on how many rows I want the display to stretch.

I want to display various images that have different ratio (think pinterest) so that ratio of col versus row might not always work. Is there any way to do so with material design without having to crop the picture or strech them?

PS : I am aware of Disandro's masonry, I am looking for a pure material design solution.

I reused the code from here : https://material.angularjs.org/#/demo/material.components.gridList

Thanks

Matthieu
  • 337
  • 4
  • 17
  • Did you find the solution for this? Actually you can use the same thing as for doing it masonry-like, but you can use, e.g. 1px columns. – kuzzmi Jun 16 '15 at 21:30
  • Hi, thanks for the reply. No I haven't yet. I am not sure I understand what you mean. What I would need to do is decide on the height of tile in px based on the width I think. – Matthieu Jun 19 '15 at 12:10

2 Answers2

3

Kuzzmi, you are a genius Something like this worked (to be improved)

1- You make md-grid-list the same amount of columns than the width of your container

2- the md-rowspan and md-colspan needs to have the size of the image. I am sure there are things to improve (window resize, etc... but the idea is there)

Happy to hear your thoughts

<md-grid-list md-cols="1133" md-row-height="1:1">
<md-grid-tile ng-repeat="i in images" md-rowspan="{{i.h}}" md-colspan="{{i.w}}">
  <img ng-src="{{i.src}}"/>
  <md-grid-tile-footer>
    <h3>{{i.title}}</h3>
  </md-grid-tile-footer>
</md-grid-tile>

Matthieu
  • 337
  • 4
  • 17
  • Yep, I meant something like this. It works as expected though it's not the most elegant solution. – kuzzmi Jun 20 '15 at 13:15
1

I did it by choosing even rows for lg view and even columns for smaller screens. I choose 12 for the "even" value and then I played with md-cols for the different sizes. This gives me 1 column on phones, two equal width columns on tablets and multiple equal height rows on larger screens.

I calculate the ratio of the tile by finding the closest aspectratio from a predifinded set. Some cropping always appear but it is quite minimal. One could also just skip the whole ratios thing and just calculate the missing value by image.width/image.height*12.

css

md-grid-tile {
    transition: all 500ms ease-out 100ms;
    overflow: hidden;
    img{
      width: 100%;
      height: auto;
    }
}

template:

<md-grid-list
    md-cols="12" md-cols-gt-sm="24" md-cols-gt-lg="72"
    md-row-height="1:1"
    md-gutter="2px" md-gutter-gt-sm="4px" >
        <md-grid-tile ng-repeat="image in images"
            md-rowspan="{{getRowspan(article)}}"
            md-rowspan-gt-lg="{{getRowspan(image,'lg')}}"
            md-colspan="{{getColspan(article)}}"
            md-colspan-gt-lg="{{getColspan(image,'lg')}}"
            class="md-whiteframe-z2" >
                <img ng-src="{{image.src}}" />
                <md-grid-tile-footer>
                    <h3 article-title="image.title"></h3>
                </md-grid-tile-footer>
        </md-grid-tile>
</md-grid-list>

controller:

    $scope.ratios = [
        3/12,
        6/12,
        9/12,
        12/12,
        15/12,
        18/12,
        21/12
    ]
    $scope.getRowspan = function(image,size){
        switch (size) {
            case 'lg':
                return 12;
            default:
                var ratio = image.meta.height / image.meta.width;
                var i;
                for (i = $scope.ratios.length; i > 0; i--) {
                    var cur = $scope.ratios[i - 1];
                    if (!angular.isDefined($scope.ratios[i - 2]) || ratio > cur) {
                        ratio = cur;
                        break;
                    }
                }
                return ratio * 12;
        }
    };
    $scope.getColspan = function(image,size){
        switch (size) {
            case 'lg':
                var ratio = image.meta.width / image.meta.height;
                var i;
                for (i = 0; i < $scope.ratios.length; i++) {
                    var cur = $scope.ratios[i];
                    if (!angular.isDefined($scope.ratios[i + 1]) || ratio < cur) {
                        ratio = cur;
                        break;
                    }
                }
                return ratio * 12;
            default:
                return 12;
        }
    };