모서리가 있는 석공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
하고 있는 하고 있다.reload
brick
이 버전은 목록 전체를 변경할 때 새로고침이 한 번만 트리거됩니다.
방법은 매우 간단합니다.
- 새 규 록 등 register new신
bricks
in parent 부모로서masonry
controller
$watch
for changes in the registered 등기부 변경에 대하여bricks
and fire 그리고 발사한다masonry('reload')
- 거 한 remove다제?
brick
부에서bricks
요소를 제거하면 레지스트리 - 거 지 스 트 리 registry - - the when element are레요제 you)를 제거하면 됩니다.$on('$destroy')
- ?
- 이익
을 확장하면 을 할 수 할 수 있습니다).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단계로 진행됩니다.
- 이미지가 로드될 때까지 기다립니다(루프에서 마지막 이미지가 추가된 경우 - jQuery images loaded 플러그인을 사용합니다).
- 모든 이미지가 '완료'될 때까지 기다립니다.
- 이미지를 레이아웃합니다.
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
'programing' 카테고리의 다른 글
"True"(JSON)를 Python 등가 "True"(참)로 변환 (0) | 2023.03.11 |
---|---|
AngularJS가 개발 시스템에서 부분 캐시를 사용하지 않도록 설정함 (0) | 2023.03.11 |
이벤트 개체에서 데이터 속성에 액세스하는 방법 (0) | 2023.03.11 |
페이지 번호 장식을 사용하지 않고 ngTable을 렌더링하려면 어떻게 해야 합니까? (0) | 2023.03.11 |
Active Model을 사용하여 동일한 모델에 여러 개의 다른 시리얼라이저를 구현하는 방법:시리얼라이저? (0) | 2023.03.06 |