Бесконечная прокрутка Белый фон при прокрутке - PullRequest
0 голосов
/ 19 апреля 2020

Я пытаюсь реализовать бесконечную прокрутку. Я использовал этот подход. Вроде все работает нормально. Но при выполнении прокрутки, вместо реального дома появляется какой-то белый фон. Я проверил, что дом уже добавлен в сетку, хотя белый фон приходит. Я приложил свой код здесь. Пожалуйста, помогите мне исправить. Codepen

Примечание. Чтобы воспроизвести, откройте в режиме просмотра полной страницы и попробуйте прокрутить во всех направлениях. (Иногда это не происходит при вертикальной прокрутке, но она определенно воспроизводима при вертикальной прокрутке в противоположную сторону. .)

const TOP = 0;
const LEFT = 1;
const RIGHT = 2;
const BOTTOM = 3;

const PADDING_COUNT = 2; // Extra DOM Count will be rendered on each side of grid.
const PREPOPULATION_COUNT = 25; // Rendered on Scroll Direction
const SCROLL_RUNWAY = 2000;
var i = 0,
  j = 0,
  len = 0,
  scrollleft, scrolltop, cell, node, coords;



class Grid {

  constructor(source, scroller) {
    this.source = source;
    this.scroller = scroller;
    this.scrollerHeight = this.scroller.offsetHeight;
    this.scrollerWidth = this.scroller.offsetWidth;
    this.boundries = [0, 0, 0, 0];
    this.scrollTop = 0;
    this.scrollLeft = 0;
    this.scrollRunwayRight = 0;
    this.scrollRunwayBottom = 0;
    this.scroller.classList.add('grid');
    //RUN WAY PREPARATION
    this.scrollRunway = document.createElement('div');
    this.scrollRunway.textContent = ' ';
    this.scrollRunway.style.position = 'absolute';
    this.scrollRunway.style.height = '1px';
    this.scrollRunway.style.width = '1px';
    this.scrollRunway.style.transition = 'transform 0.2s';
    this.scroller.append(this.scrollRunway);

    this.unusednodes = [];
    //EVENT PREPARATION
    this.scroller.addEventListener('scroll', this.onResize.bind(this));
    window.addEventListener('resize', this.onResize.bind(this));


    this.dom = [];
    this.map = {};
    this.linkedGrids = [];
    this.cellWidth = this.source.getCellWidth();
    this.cellHeight = this.source.getCellHeight();
    this.onResize();
  }

  syncGrid(sl, st) {
    this.linkedGrids.forEach(grid => {
      //sync each grid 
    });
  }

  onResize() {
    this.scrollerHeight = this.scroller.offsetHeight;
    this.scrollerWidth = this.scroller.offsetWidth;
    this.onScroll();
  }

  fillGrid(left, right, top, bottom) {
    //console.log("left=",left,"right=",right,"top",top,"bottom",bottom);
    len = this.dom.length;
    var latest = [];
    //Clear Unnecessary DOM
    this.map = {};
    for (i = 0; i < len; i++) {
      cell = this.dom[i];
      if (cell.row <= bottom && cell.row >= top && cell.col >= left && cell.col <= right) {
        this.map[cell.row + '' + cell.col] = true;
        latest.push(cell);
        continue;
      }
      this.unusednodes.push(cell.node);
      this.map[cell.row + '' + cell.col] = false;
    }
    this.dom = latest;

    //Create New DOM
    for (i = top; i <= bottom; i++) {
      for (j = left; j <= right; j++) {
        if (!this.map[i + '' + j]) {
          node = this.source.render(this.getFreeNode(), i, j);
          this.dom.push({
            row: i,
            col: j,
            node: node
          });
          coords = this.source.getCellCoordinates(i, j);
          node.style.transform = 'translate(' + coords.y + 'px,' + coords.x + 'px)'; //left,top,z
          this.scroller.append(node);
        }
      }
    }
    coords = this.source.getCellCoordinates(right, bottom);
    this.scrollRunwayRight = Math.max(this.scrollRunwayRight, coords.y + SCROLL_RUNWAY);
    this.scrollRunwayBottom = Math.max(this.scrollRunwayBottom, coords.x + SCROLL_RUNWAY);
    this.scrollRunway.style.transform = 'translate(' + this.scrollRunwayRight + 'px,' + this.scrollRunwayBottom + 'px)';

    //Clean Empty Nodes
    while (this.unusednodes.length) {
      this.unusednodes.pop().remove();
    }
  }

  onScroll() {
    scrollleft = this.scroller.scrollLeft;
    scrolltop = this.scroller.scrollTop;
    i = scrollleft - this.scrollLeft;
    j = scrolltop - this.scrollTop;
    if (i == 0 && j == 0) {
      this.boundries[LEFT] = Math.max(0, Math.floor(scrollleft / this.cellWidth));
      this.boundries[RIGHT] = Math.floor((scrollleft + this.scrollerWidth) / this.cellWidth);
      j = 1;
    }

    if (Math.abs(i) > Math.abs(j)) {
      this.boundries[LEFT] = Math.max(0, Math.floor(scrollleft / this.cellWidth));
      this.boundries[RIGHT] = Math.floor((scrollleft + this.scrollerWidth) / this.cellWidth);
      if (i > 0) {
        //console.log("horizontal forward");
        this.fillGrid(this.boundries[LEFT], this.boundries[RIGHT] + PREPOPULATION_COUNT, this.boundries[TOP], this.boundries[BOTTOM]);
      } else if (i < 0) {
        // console.log("hoirzontal backward");
        this.fillGrid(Math.max(0, this.boundries[LEFT] - PREPOPULATION_COUNT), this.boundries[RIGHT], this.boundries[TOP], this.boundries[BOTTOM]);
      }
    } else if (Math.abs(i) < Math.abs(j)) {
      this.boundries[TOP] = Math.max(0, Math.floor(scrolltop / this.cellHeight));
      this.boundries[BOTTOM] = Math.floor((scrolltop + this.scrollerHeight) / this.cellHeight);
      if (j > 0) {
        // console.log("vertical forward");
        this.fillGrid(this.boundries[LEFT], this.boundries[RIGHT], this.boundries[TOP], this.boundries[BOTTOM] + PREPOPULATION_COUNT);
      } else if (j < 0) {
        //   console.log("vertical backward");
        this.fillGrid(this.boundries[LEFT], this.boundries[RIGHT], Math.max(0, this.boundries[TOP] - PREPOPULATION_COUNT), this.boundries[BOTTOM]);
      }
    }

    this.scrollLeft = scrollleft;
    this.scrollTop = scrolltop;
  }


  getFreeNode() {
    if (this.unusednodes.length) {
      return this.unusednodes.pop();
    }
    return this.source.getTombstone();
  }
}









class ContentSource {

  constructor(row, col) {
    this.no_of_columns = col;
    this.no_of_rows = row;
    this.row_height = 40;
    this.column_width = 180;
    this._cellnode = document.querySelector("#CELL_TEMPLATE");
  }

  getCellWidth() {
    return this.column_width;
  }

  getCellHeight() {
    return this.row_height;
  }

  getNumberOfRows() {
    return this.no_of_rows;
  }

  getNumberOfColumns() {
    return this.no_of_columns;
  }


  getCellCoordinates(row_id, col_id) {
    return {
      x: row_id == 0 ? 0 : (row_id) * this.row_height,
      y: col_id == 0 ? 0 : (col_id) * this.column_width
    };
  }

  getTombstone() {
    return this._cellnode.content.cloneNode(true).firstElementChild;
  }

  render(div, row, col) {
    div = div || this.getTombstone();
    div.querySelector('.cell-content').textContent = row + '-' + col;
    return div;
  }

}



var source = new ContentSource(10000, 100);
window.scroller = new Grid(source, document.getElementById('grid'));
html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
}


/* Cell Common to All  */

.cell {
  position: absolute;
  width: 180px;
  height: 40px;
  display: flex;
  align-items: middle;
  justify-content: flex-start;
  border-right: 1px solid #e2e8f0;
  border-bottom: 1px solid #e2e8f0;
  /* border-radius:3px; */
  text-align: center;
  box-sizing: border-box;
  contain: layout;
  will-change: transform;
}

.cell-content {
  padding: 10px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cell[data-type='number'] {
  justify-content: flex-end;
}

.cell[data-type='text'] {
  justify-content: flex-start;
}

.cell[data-type='date'] {
  justify-content: flex-end;
}

.grid {
  margin: 0;
  padding: 0;
  overflow: scroll;
  -webkit-overflow-scrolling: touch;
  width: 100%;
  height: 100%;
  position: absolute;
  box-sizing: border-box;
  contain: layout;
  will-change: transform;
  border: 1px solid #e2e8f0;
}
<div id="grid" class='grid-class'></div>
<template id='CELL_TEMPLATE'>   
  <div class="cell" data-type='text'><span class='cell-content'>sample</span></div>
</template>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...