1. Anuncie Aqui ! Entre em contato fdantas@4each.com.br

Item layout overlap only first time render that content

Discussão em 'Angular' iniciado por yash chapani, Outubro 10, 2024 às 06:42.

  1. yash chapani

    yash chapani Guest

    When I used the custom masonry package implement on the angular with help of custome directive then first time content overlapped, I did not calculate proper position Why did this happen?

    I check debug then targetindex not proper someTime that's why they overlap with above content so What can i do?

    I think the issue happened only in the directive.

    enter image description here

    import { Directive, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, Output, Renderer2 } from '@angular/core';
    import $ from 'jquery';

    @Directive({
    selector: '[appPinGrid]',
    // standalone: true
    })
    export class PinGridDirective implements OnChanges, OnDestroy {

    @Input()
    gutter: number = 0;

    @Input()
    columns: number = 0;

    @Input()
    minColWidth: number = 2;

    @Input()
    maxColWidth: number = 10;

    @Input()
    doubleColumnWidth: number = 10;

    @Input()
    itemClass: string = '';

    @Input() public data: any;

    @Output() onLayoutComplete: EventEmitter<any> = new EventEmitter();

    container: any;
    containerWidth: number = 0;
    containeHeight: number = 0;
    columnWidth: any;
    items: any;

    // columns of grid
    columnHeightArray: any;

    // timer for detect changes
    controlSkipper: any;
    resizeControlSkipper: any;

    // host listener for resize window
    // resizeListener: any;

    isSearchFirstTime: any = true;
    constructor(public el: ElementRef, public renderer: Renderer2) { }
    ngOnDestroy() {
    // unsubscribe event listener
    this.resizeListener();
    }

    resizeListener(){
    this.renderer.listen('window', 'resize', () => {
    if (this.resizeControlSkipper)
    clearTimeout(this.controlSkipper)
    this.resizeControlSkipper = setTimeout(() => {
    // console.log('relayout call');
    this.reLayout();
    }, 400);
    });
    }


    ngOnChanges(changes: { data: any; }) {
    if (this.isSearchFirstTime) {
    this.isSearchFirstTime = false;
    // this is for skip first changes detect for initialieze all directive (scroll unnecessary api of second page from here so this solution is apply)
    } else {
    if (changes.data) {
    if (this.controlSkipper)
    clearTimeout(this.controlSkipper)

    this.controlSkipper = setTimeout(async () => {
    this.reLayout();
    }, 500);
    }
    }
    }

    reLayout() {
    // console.log('relayout');
    this.container = this.el.nativeElement;
    this.items = this.el.nativeElement.childNodes;
    this.items.forEach((element: any) => {
    $(element).css('opacity', '0');
    });
    this.layoutItem();
    }

    async layoutItem() {
    // console.log('layout');
    this.getColumnWidth();
    this.initColumnHeightarray();

    for (var i = 0; i < this.items.length; i++) {
    this.placeItem(this.items);
    }
    this.items.forEach((element: any) => {
    console.log('element: ', element);
    $(element).css('opacity', '1');
    });
    console.log('layout complete in function');
    await $(this.container).height(Math.max.apply({}, this.columnHeightArray));
    // console.log('set wrapper height', Math.max.apply({}, this.columnHeightArray));
    await this.onLayoutComplete.emit('LayoutComplete');
    }

    initColumnHeightarray() {
    this.resetColumnHeight();
    for (var i = 0; i < this.columns; i++) {
    this.columnHeightArray.push(0);
    }
    }

    resetColumnHeight() {
    this.columnHeightArray = [];
    }

    getColumnWidth() {
    this.containerWidth = this.el.nativeElement.offsetWidth;
    this.columnWidth = Math.floor((this.containerWidth / this.columns) - this.gutter);
    if (this.columnWidth <= Number(this.minColWidth) && this.columns >= 2) {
    this.columns--;
    this.getColumnWidth();
    }
    // in below condition I check double column width
    // because column minus if card width < 200 and suppose column = 1 then it's width is increase
    // now maximum card width is 300 and container is about 465(200 column width + 2 number of column + 2 * gutter size) something, so that, below condition is become true and add one column i.e. 2.
    // now two column card width is again < 200 thus it will gose to infonite.
    // so I check that if container have enough space to display two column then I add column othersize it will display only one column
    if (this.columnWidth >= Number(this.maxColWidth) && this.containerWidth > this.doubleColumnWidth) {
    this.columns++;
    this.getColumnWidth();
    }
    }

    calculateImageSize() {
    }

    async placeItem(item: { nodeType: number; getElementsByClassName: (arg0: string) => { (): any; new(): any; length: number; }; }) {
    if (item.nodeType != Node.ELEMENT_NODE) {
    return; // Skip non-element nodes
    }

    // Find the column with the minimum height
    const minimumColHeight = Math.min.apply({}, this.columnHeightArray);
    const minColIndex = $.inArray(minimumColHeight, this.columnHeightArray);

    // Calculate the position
    const targetIndex = minColIndex;
    const fixMarginLeft = (this.containerWidth - this.columnWidth * this.columns - this.gutter * (this.columns - 1)) / 2;

    // If the item has the specified class, adjust its size
    if (item.getElementsByClassName(this.itemClass).length > 0) {
    const img = item.getElementsByClassName(this.itemClass)[0];
    $(img).css('position', 'initial');
    // Ensure width and height are correctly set for proper placement
    const aspectRatio = $(img).width() / ($(img).height() || 1);
    $(img).css('width', this.columnWidth);
    $(img).css('height', Math.floor(this.columnWidth / aspectRatio));
    }

    // Calculate the position for the item
    console.log('this.columnHeightArray[targetIndex]: ', this.columnHeightArray[targetIndex]);
    const position = {
    left: (this.columnWidth + this.gutter) * targetIndex + fixMarginLeft,
    top: this.columnHeightArray[targetIndex] + this.gutter // Adding gutter to the top position
    };

    // Position the item
    $(item).css('position', 'absolute');
    $(item).css('top', position.top);
    $(item).css('left', position.left);

    // Update the column height to account for the new item
    this.columnHeightArray[targetIndex] += $(item).outerHeight() + this.gutter; // Update column height including gutter
    console.log('this.columnHeightArray[targetIndex]: ', this.columnHeightArray[targetIndex]);
    }

    }



    I want to do proper adjust position how can i do?

    Continue reading...

Compartilhe esta Página