Chrome делит веб-страницу на плитки, называемые составными слоями, которые затем окрашиваются в соответствии с заданной позицией прокрутки.

2. Карты

Карты также разделены на тайлы, поэтому загружаются и отображаются на экране только определенные регионы.

Как мы видим, они оба получают необходимые ресурсы. У них также есть возможность повторно использовать ресурсы в процессе, называемом переработкой.

В мире мобильной разработки переработка реализована в Cocoa Touch и Android SDK.

Давайте рассмотрим, как переработка обрабатывается в Cocoa Touch:

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"cell1"];
    if ( cell==nil ) {
      // Allocate a new cell
    }
   // Set the model for the cell
}

Это метод делегата, используемый для запроса ячеек. Эта установка пытается повторно использовать ячейку, которая больше не видна, или создаст новую, если ни одна из них недоступна. Преимущество этого заключается в том, что для обновления строк требуется меньше энергии и памяти.

Мы хотели реализовать аналогичный подход для нашего мобильного веб-приложения, загружая новые транзакции по мере прокрутки страницы пользователем.

Ключевые наблюдения

  1. Каждая строка имела одинаковую высоту, поэтому мы могли получить позицию любой данной строки за постоянное время, не запрашивая напрямую у браузера.
  2. У нас было два типа строк, нечетные и четные строки. Оба ряда имели определенные стили. Например, нечетные строки имели более светлый цвет фона по сравнению с четными строками.

Реализация прокрутки

Когда мы начинали проект, не было встроенного свойства CSS для прокрутки, которое принимали бы все веб-браузеры, на которые мы ориентировались. Мы хотели сохранить стиль импульса, характерный для нативных приложений. Для нас решением стала iScroll, библиотека JavaScript, решающая проблему кроссбраузерности.

Прежде чем приступить к реализации бесконечной прокрутки, нам нужно было придать определенную структуру данным, поступающим от службы RESTful. Мы использовали Backbone.js во всем приложении, поэтому мы определили Model, View и Collection следующим образом:

Модель

Модель состоит из важной информации о статусе транзакции в PayPal.

{
 "id": "1",
 "name": "Pizza Restaurant",
 "status": "completed",
 "amount": "10.0",
 "currency": "USD",
 "date": "2013-12-01T19:20:30+01:00"
}

Часть этой информации отображается в списке действий, а другая является дополнительной для взаимодействия с деталями.

Вид

Приложение имеет основное представление, называемое CellView, которое расширяется представлениями OddCellView и EvenCellView.

var CellView = Backbone.View.extend({
  tagName: "div",
  className: "ui-cell-view"
});
var OddCellView = CellView.extend({
  className: "ui-cell-view ui-cell-view-odd"
});
var EvenCellView = CellView.extend({
  className: "ui-cell-view ui-cell-view-even"
});
The two child classes are meant to represent different objects that share the same functionality but different looking as their className suggests. The benefit from explicitly defining this in the code rather than letting the browser guess it (using :even and :odd pseudo classes) is the Cell Recycling process that will be covered next.
Since all the cells have the same height and are the only one in a row, we can determine the total number of rows we need given a scrolling area height.
TotalRows = (ScrollingAreaHeight / RowHeight) * 3/2
The 3/2 factor means that it will have 1.5 times more rows than the visibles to the user.

Коллекция

As PayPal users may have lots of activity status, the app needed to fetch them efficiently. Backbone collections was the structure that helped us to keep the data organized in the client. We built a paging mechanism that fetches models on-demand, so as the user scrolls it will ask for data when there is not enough models to cover the scrolling area. The collection had a limit of 100 contiguous models.
One of the benefits of this separation in the client is that once a model is stored in the client, there’s no need to ask the server for more information about that particular transaction which helps to reduce the stress on the servers.
Putting all pieces together
Now that we have the structure of the data and the views, we can start working on the implementation of the infinite scroll. The core of the infinite scroll is the ability to reuse cells that are no longer visible.
When a cell (DOM element) is rendered in the browser, we create its own composited layer by adding the 3D transform property that gives its position on the scrolling area. This composited layer is then uploaded to the GPU as the cell represents the smallest portion of the scrolling area that can be split into tiles. The implementation also had a composited layer for the scroller (implemented by iScroll) which gives the momentum feeling.
We wanted to avoid operations like: change the background color, change the class selectors, or change the entire subtree of the cell because they invalidate the texture in the GPU causing overhead and in some situations a disgraceful blinking effect.
The recycling process consists on moving the least recently seen cell to the space that needs a new cell. The following graph illustrates the process:
The implementation only updates the Y component of the transformation matrix that gives the position of the cell on the screen. This update is really fast since the texture is hardware accelerated.  Next, it updates the model of the cell which indeed requires to paint the new name, status and amount of the transaction, but on a much smaller area.  Another consideration is that web browsers are highly optimized to handle modifications to Text Nodes when those do not involve alterations to the DOM structure.
Results
The scrolling feels responsive. This implementation achieved an average of 60 frame per seconds on an iPhone 5, and here’s what the frame graph looked like on Chrome after fetching about 300 transactions.
Here’s a screenshot of the PayPal User’s Activity.
If you're interested in an internship at PayPal please visit our Student Careers site.