Skip to content

Instantly share code, notes, and snippets.

@aroben
Last active August 29, 2015 13:55
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save aroben/8689243 to your computer and use it in GitHub Desktop.
Chromium Infinite Scrolling Demo

This demo comes from Chromium's source repository. See the original here.

The scrollable area represents 500 "virtual" items (kNumberOfItems) using 30 "physical" DOM elements (kPhysicalCount). As elements get scrolled out of view to the top, they get moved down to the bottom via -webkit-transform: translate3d(0, NNNpx, 0) and their contents get replaced with the appropriate "virtual" item. requestAnimationFrame() is used to ensure that updates only happen once per repaint of the window.

<!doctype html>
<!--
Copyright 2013 The Polymer Authors. All rights reserved.
Use of this source code is governed by a BSD-style
license that can be found in the LICENSE file.
-->
<html>
<head>
<title>infinite-scroll</title>
<meta name="viewport" content="width=device-width, user-scalable=no">
<style>
html {
height: 100%;
}
body {
display: block;
height: 100%;
margin: 0;
}
#container {
overflow-y: scroll;
height: 100%;
margin: 0;
}
#runway {
height: 100000px;
}
.item {
-webkit-transform: translate3d(0,0,0);
box-sizing: border-box;
overflow: hidden;
}
.conversation {
font-family: sans-serif;
height: 70px;
display: flex;
border-bottom: 1px solid lightgray;
}
.avatar {
display: flex;
flex-shrink: 0;
color: white;
align-items: center;
justify-content: center;
font-size: 40px;
width: 50px;
height: 50px;
margin: 10px;
background-color: lightblue;
}
.summary {
flex: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
padding: 10px 10px 10px 0px;
}
.topline {
display: flex;
flex-shrink: 0;
}
.participants {
flex: 1;
flex-shrink: 0;
font-weight: bold;
}
.time {
flex-shrink: 0;
font-size: 12px;
color: #444;
}
.bottomline {
flex-shrink: 0;
display: flex;
}
.preview {
flex: 1;
flex-shrink: 0;
font-size: 12px;
height: 2em;
text-overflow: ellipsis;
}
.subject {
font-weight: bold;
}
.snippet {
color: #444;
}
.trinkets {
flex-shrink: 0;
font-size: 20px;
}
</style>
</head>
<body>
<div id="container">
<div id="runway">
<template>
<div class="item conversation">
<div class="avatar">A</div>
<div class="summary">
<div class="topline">
<div class="participants">{{ participants }}</div>
<div class="time">{{ time }}</div>
</div>
<div class="bottomline">
<div class="preview"><span class="subject">{{ subject }}</span> &mdash;
<span class="snippet">{{ snippet }}</span></div>
<div class="trinkets">&#x2606;</div>
</div>
</div>
</div>
</template>
</div>
</div>
<script>
function getRandomItem(array) {
return array[Math.floor(Math.random() * array.length)];
}
function generateFakeData() {
var kNumberOfItems = 500;
var possibleParticipants = [
'Adam', 'Ojan', 'Elliot', 'Chris',
];
var possibleTimes = [
'Now', 'Yesterday', 'Last week',
];
var possibleSubjects = [
'Do you even bench?',
'I like to scroll forever',
'Lunch',
'What if my subject is really long? Longer than that. Like really, really, long?',
];
var possibleSnippets = [
'Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal.',
'When, in disgrace with fortune and men\'s eyes, I all alone beweep my outcast state,',
'We the People of the United States, in Order to form a more perfect Union, establish Justice, insure domestic Tranquility',
];
var data = new Array(kNumberOfItems);
for (var i = 0; i < kNumberOfItems; ++i) {
data[i] = {
participants: getRandomItem(possibleParticipants),
time: getRandomItem(possibleTimes),
subject: getRandomItem(possibleSubjects),
snippet: getRandomItem(possibleSnippets),
}
console.log(data[i]);
}
return data;
}
var data = generateFakeData();
"use strict";
(function(exports) {
var kHeight = 70;
var kPhysicalCount = 30;
var container = document.getElementById('container');
var runway = document.getElementById('runway');
var template = runway.querySelector('template');
var items = new Array(kPhysicalCount);
for (var i = 0; i < kPhysicalCount; ++i) {
var fragment = template.content.cloneNode(true);
runway.appendChild(fragment);
var item = runway.lastElementChild;
items[i] = item;
item.transformValue_ = 0;
item.participants_ = item.querySelector('.participants').firstChild;
item.time_ = item.querySelector('.time').firstChild;
item.subject_ = item.querySelector('.subject').firstChild;
item.snippet_ = item.querySelector('.snippet').firstChild;
updateText(item, i);
}
var physicalHeight = kHeight * kPhysicalCount;
function updateText(item, index) {
var datum = data[index % data.length];
item.participants_.nodeValue = datum.participants;
item.time_.nodeValue = datum.time;
item.subject_.nodeValue = datum.subject;
item.snippet_.nodeValue = datum.snippet;
}
container.addEventListener('scroll', function(e) {
var scrollTop = container.scrollTop;
var firstVirtualIndex = Math.floor(scrollTop / kHeight);
var firstPhysicalIndex = firstVirtualIndex % kPhysicalCount;
var baseVirtualIndex = firstVirtualIndex - firstPhysicalIndex;
var baseTransformValue = kHeight * baseVirtualIndex;
var nextTransformValue = baseTransformValue + physicalHeight;
var baseTransformString = 'translate3d(0,' + baseTransformValue + 'px,0)';
var nextTransformString = 'translate3d(0,' + nextTransformValue + 'px,0)';
window.requestAnimationFrame(function() {
for (var i = 0; i < firstPhysicalIndex; ++i) {
var item = items[i];
if (item.transformValue_ != nextTransformValue) {
updateText(item, baseVirtualIndex + kPhysicalCount + i);
item.style.WebkitTransform = nextTransformString;
}
item.transformValue_ = nextTransformValue;
}
for (var i = firstPhysicalIndex; i < kPhysicalCount; ++i) {
var item = items[i];
if (item.transformValue_ != baseTransformValue) {
updateText(item, baseVirtualIndex + i);
item.style.WebkitTransform = baseTransformString;
}
item.transformValue_ = baseTransformValue;
}
});
});
})(window);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment