programing

모서리가 있는 석공JS

testmans 2023. 3. 11. 08:44
반응형

모서리가 있는 석공JS

는 '아트갤러리' 앱을 개발하고 있습니다.

github소스를 자유롭게 끌어내리고 가지고 놀아라.

풀 소스 플런커

Masonry가 Angular와 잘 어울리도록 하기 위한 현재 작업은 다음과 같습니다.

.directive("masonry", function($parse) {
  return {
    restrict: 'AC',
    link: function (scope, elem, attrs) {
      elem.masonry({ itemSelector: '.masonry-brick'});
    }
  };     
})
.directive('masonryBrick', function ($compile) {
  return {
    restrict: 'AC',
    link: function (scope, elem, attrs) {
      scope.$watch('$index',function(v){
        elem.imagesLoaded(function () {
          elem.parents('.masonry').masonry('reload');
        });
      });
    }
  };    
});

이 방법은 다음과 같은 이유로 올바르게 동작하지 않습니다.

  • 콘텐츠가 증가함에 따라 전체 컨테이너에 대한 티거링 새로고침의 오버헤드도 증가합니다.

reload★★★★

  • 항목을 "추가"하지 않고 용기 내의 모든 항목을 다시 정렬합니다.
  • 결과 집합에서 항목이 필터링될 때 새로고침을 트리거하는 데 사용됩니다.

위에서 링크한 앱에서는 이 문제를 쉽게 재현할 수 있습니다.

지침을 사용하여 다음을 활용할 수 있는 솔루션을 찾고 있습니다.

.masonry('appended', elem) ★★★★★★★★★★★★★★★★★」.masonry('prepended', elem)

" " 를 실행하는 것이 " " 를 하는 것입니다..masonry('reload')★★★★★★ 。

.masonry('reload')결과 집합에서 요소를 제거할 때 사용합니다.


편집

프로젝트는 아래 현용 솔루션을 사용하도록 업데이트되었습니다.

GitHub에서 소스 가져오기

Plunker의 현용 버전을 참조해 주세요.

@ganaraj는 @ganaraj이다.$element.masonry('resize');을 빌붙여서.appendBrick이미지 로딩 방법 및 계정을 지정하면 작동되는 것처럼 보입니다.

여기 플런커 포크가 있습니다.http://plnkr.co/edit/8t41rRnLYfhOF9oAfSUA

이 작업이 필요한 이유는 요소에서 석조가 초기화되거나 컨테이너 크기가 조정될 때만 컬럼 수가 계산되며, 현 시점에서는 벽돌을 얻지 못했기 때문에 기본적으로 단일 컬럼으로 설정됩니다.

resize 메서드를 사용하지 않는 경우(문서화되어 있지 않은 것 같습니다), $element.masonry()를 호출하면 됩니다만, 재레이아웃이 발생하므로 첫 번째 브릭이 추가되었을 때만 호출할 수 있습니다.

편집: 위의 플런커를 콜 전용으로 업데이트했습니다.resize리스트의 길이가 0을 초과하여 동일한 $120 사이클에서 여러 개의 브릭이 제거되었을 때 하나의 "실행"만 수행합니다.

지시 코드는 다음과 같습니다.

angular.module('myApp.directives', [])
  .directive("masonry", function($parse, $timeout) {
    return {
      restrict: 'AC',
      link: function (scope, elem, attrs) {
        elem.masonry({ itemSelector: '.masonry-brick'});
        // Opitonal Params, delimited in class name like:
        // class="masonry:70;"
        //elem.masonry({ itemSelector: '.masonry-item', columnWidth: 140, gutterWidth: $parse(attrs.masonry)(scope) });
      },
      controller : function($scope,$element){
          var bricks = [];
          this.appendBrick = function(child, brickId, waitForImage){
            function addBrick() {
              $element.masonry('appended', child, true);

              // If we don't have any bricks then we're going to want to 
              // resize when we add one.
              if (bricks.length === 0) {
                // Timeout here to allow for a potential
                // masonary timeout when appending (when animating
                // from the bottom)
                $timeout(function(){
                  $element.masonry('resize');  
                }, 2);  
              }

              // Store the brick id
              var index = bricks.indexOf(brickId);
              if (index === -1) {
                bricks.push(brickId);
              }
            }

            if (waitForImage) {
              child.imagesLoaded(addBrick);      
            } else {
              addBrick();
            }
          };

          // Removed bricks - we only want to call masonry.reload() once
          // if a whole batch of bricks have been removed though so push this
          // async.
          var willReload = false;
          function hasRemovedBrick() {
            if (!willReload) {
              willReload = true;
              $scope.$evalAsync(function(){
                willReload = false;
                $element.masonry("reload");
              });
            }
          }

          this.removeBrick = function(brickId){
              hasRemovedBrick();
              var index = bricks.indexOf(brickId);
              if (index != -1) {
                bricks.splice(index,1);
              }
          };
      }
    };     
  })
  .directive('masonryBrick', function ($compile) {
    return {
      restrict: 'AC',
      require : '^masonry',
      link: function (scope, elem, attrs, MasonryCtrl) {

      elem.imagesLoaded(function () {
        MasonryCtrl.appendBrick(elem, scope.$id, true);
      });

      scope.$on("$destroy",function(){
          MasonryCtrl.removeBrick(scope.$id);
      }); 
    }
  };
});

것이 .prepend ★★★★★★★★★★★★★★★★★」append필요한 것은 다음과 같습니다.

http://plnkr.co/edit/dmuGHCNTCBBuYpjyKQ8E?p=preview

하고 있는 하고 있다.reloadbrick이 버전은 목록 전체를 변경할 때 새로고침이 한 만 트리거됩니다.

방법은 매우 간단합니다.

  1. 새 규 록 등 register new신bricks in parent 부모로서masonry controller
  2. $watch for changes in the registered 등기부 변경에 대하여bricks and fire 그리고 발사한다masonry('reload')
  3. 거 한 remove다제?brick부에서bricks요소를 제거하면 레지스트리 - 거 지 스 트 리 registry - - the when element are레요제 you)를 제거하면 됩니다.$on('$destroy')
  4. ?
  5. 이익

을 확장하면 을 할 수 할 수 있습니다).prepend ★★★★★★★★★★★★★★★★★」append하지만 당신이 그렇게 하고 싶어할 이유는 전혀 없습니다.요소의 순서를 수동으로 추적해야 하므로 이 작업은 훨씬 더 복잡해집니다.는 또한 빠를 -도 있다, 번 때문이다 - 그것은 더 느릴 수도 있다.append/prepend츠키노

만, ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★.ng-animate(「」의)JavaScript★★★★★★★★★★★★★★★★★★★」

,그러다,그러다,그러다,그러다,그러다,.tiling을 사용하다이 솔루션이 가장 빠른 것으로 나타났습니다.더 나은 해결책을 가진 사람이 있다면 보고 싶어요.

코드를 사용하려는 사용자:

angular.module('myApp.directives', [])
  .directive("masonry", function($parse) {
    return {
      restrict: 'AC',
      controller:function($scope,$element){
        // register and unregister bricks
        var bricks = [];
        this.addBrick = function(brick){
          bricks.push(brick)
        }
        this.removeBrick = function(brick){
          var index = bricks.indexOf(brick);
          if(index!=-1)bricks.splice(index,1);
        }
        $scope.$watch(function(){
          return bricks
        },function(){
          // triggers only once per list change (not for each brick)
          console.log('reload');
          $element.masonry('reload');
        },true);
      },
      link: function (scope, elem, attrs) {
        elem.masonry({ itemSelector: '.masonry-brick'});
      }
    };     
  })
  .directive('masonryBrick', function ($compile) {
    return {
      restrict: 'AC',
      require:'^masonry',
      link: function (scope, elem, attrs,ctrl) {
        ctrl.addBrick(scope.$id);

        scope.$on('$destroy',function(){
          ctrl.removeBrick(scope.$id);
        });
      }
    };
  });

편집: (이미지 로딩)에 대해 잊어버린 것이 하나 있습니다. 모든 이미지가 로딩되면 '다시 로드'를 호출합니다.나중에 코드를 편집해 보겠습니다.

방금 앵귤러에게 석조 지령을 내렸어요JS는 지금까지 본 대부분의 구현보다 훨씬 단순합니다.자세한 내용은 이쪽을 참조해 주세요.https://gist.github.com/CMCDragonkai/6191419

AMD와 호환됩니다.jQuery, 이미지 필요로딩 및 로더시.동적 항목 수, AJAX 로드된 항목(초기 항목도 포함), 창 크기 조정 및 사용자 지정 옵션과 함께 작동합니다.추가 항목, 추가 항목, 다시 로드된 항목...기타 73줄!

http://plnkr.co/edit/ZuSrSh?p=preview (AMD는 사용하지 않지만 동일한 코드)가 동작하고 있음을 나타내는 plunkr을 나타냅니다.

Angular의 가장 문서화된 기능 중 하나는 Directive Controller입니다(단, www.angularjs.org - Tabs 의 첫 페이지에 기재되어 있습니다).

이 메커니즘을 이용한 수정된 플런커입니다.

http://plnkr.co/edit/NmV3m6DZFSpIkQOAjRRE

사람들은 Directive Controller를 사용하지만, 그것은 아마도 의도하지 않은 것에 사용되어 왔다(그리고 남용되었다).

위 플런커에서는 directives.js 파일만 수정했습니다.디렉티브 컨트롤러는 디렉티브 간의 통신 메커니즘입니다.한 가지 지시로 모든 것을 수행하는 것은 충분하지 않거나 쉽지 않을 수 있습니다.이 경우 이미 2개의 디렉티브를 작성했지만 이들 디렉티브컨트롤러를 사용하는 것이 올바른 방법입니다.

당신이 언제 추가하기를 원하는지 언제 추가하기를 원하는지 알 수가 없었어요.저는 현재 "append"만 구현했습니다.

또 한 가지 주의: 리소스가 약속을 아직 구현하지 않은 경우 직접 구현할 수 있습니다.그렇게 하는 것은 정말 어렵지 않다.콜백 메커니즘을 사용하고 있는 것을 알았습니다(권장하지 않습니다).당신은 이미 거기에 약속을 했지만, 왜 그런지 이해할 수 없는 콜백을 사용하고 있습니다.

이것이 당신의 문제에 대한 적절한 해결책을 제공합니까?

매뉴얼에 대해서는http://http://docs.angularjs.org/guide/directive > Directive Definition Object > controller 를 참조해 주세요.

저도 똑같은 문제를 겪었다고 생각합니다.

ng-repeat 루프에 있는 많은 이미지가 로드되고 준비되면 masonry/isotope를 적용하려고 합니다.

문제는 사진이 찍히고 나서도이미지가 '완전'하지 않아 제대로 측정하고 레이아웃할 수 없는 기간이 있을 경우 로드된 이미지를 다시 불러옵니다.

하나의 레이아웃 패스만 있으면 되는 다음과 같은 솔루션을 생각해 냈습니다.3단계로 진행됩니다.

  1. 이미지가 로드될 때까지 기다립니다(루프에서 마지막 이미지가 추가된 경우 - jQuery images loaded 플러그인을 사용합니다).
  2. 모든 이미지가 '완료'될 때까지 기다립니다.
  3. 이미지를 레이아웃합니다.

angularApp.directive('checkLast', function () {
    return {
        restrict: 'A',
        compile: function (element, attributes) {
            return function postLink(scope, element) {
                if (scope.$last === true) {
                    $('#imagesHolder').imagesLoaded(function () {
                        waitForRender();
                    });
                }
            }
        }
    }
});

function waitForRender() {
    //
    // We have to wait for every image to be ready before we can lay them out
    //
    var ready = true;
    var images = $('#imagesHolder').find('img');
    $.each(images,function(index,img) {
        if ( !img.complete ) {
            setTimeout(waitForRender);
            ready = false;
            return false;
        }
    });
    if (ready) {
        layoutImages();
    }
}

function layoutImages() {
    $('#imagesHolder').isotope({
        itemSelector: '.imageHolder',
        layoutMode: 'fitRows'
    });
}

이것은 다음과 같은 레이아웃으로 작동합니다.

<div id="imagesHolder">
    <div class="imageHolder"
         check-last
         ng-repeat="image in images.image"
        <img ng-src="{{image.url}}"/>
    </div>
</div>

이게 도움이 됐으면 좋겠어요.

두 가지 지시사항을 사용하는 대신 두 가지 지시사항을 모두 하나의 지시사항에 통합할 수 있습니다.예를 들어 다음과 같습니다.

.directive("masonry", function($timeout) {
    return {
        restrict: 'AC',
        template: '<div class="masonry-brick" ng-repeat="image in pool | filter:{pool:true}">' +
                        '<span>{{image.albumTitle|truncate}}</span>' +
                        '<img ng-src="{{image.link|imageSize:t}}"/>' +
                  '</div>',
        scope: {
            pool: "="
        },
        link: function(scope, elem, attrs){
            elem.masonry({itemSelector: '.masonry-brick'});

            // When the pool changes put all your logic in for working out what needs to be prepended
            // appended etc
            function poolChanged(pool) {

                //... Do some logic here working out what needs to be appended, 
                // prepended...

                // Make sure the DOM has updated before continuing by doing a $timeout
                $timeout(function(){
                    var bricks = elem.find('.masonry-brick');
                    brick.imagesLoaded(function() {
                        // ... Do the actual prepending/appending ...
                    });
                });
            }

            // Watch for changes to the pool
            scope.$watch('pool', poolChanged, true); // The final true compares for 
                                                     // equality rather than reference
        }
    }
});

및 html 사용:

<div class="masonry" pool="pool"></div>

언급URL : https://stackoverflow.com/questions/16504151/masonry-with-angularjs

반응형