kinda sorta working

This commit is contained in:
Nolan Lawson 2018-01-15 16:12:07 -08:00
parent 3f9ca66e38
commit 7682015cda
4 changed files with 47 additions and 21 deletions

View file

@ -17,7 +17,7 @@
let i = -1 let i = -1
const createData = () => fixture.slice(0, 5).map(_ => ({ const createData = () => fixture.slice(0, 20).map(_ => ({
key: `${++i}`, key: `${++i}`,
props: _ props: _
})) }))

View file

@ -1,11 +1,12 @@
<:Window bind:scrollY='scrollY'/> <:Window bind:scrollY='scrollY' bind:innerHeight='innerHeight' />
<div class="virtual-list" ref:node style="height: {{$height}}px;"> <div class="virtual-list" ref:node style="height: {{$height}}px;">
<!-- <div class="virtual-list-viewport" ref:viewport></div> --> <!-- <div class="virtual-list-viewport" ref:viewport></div> -->
{{#each $virtualItems as virtualItem, virtualIndex}} {{#each $visibleItems as item, virtualIndex}}
<VirtualListItem :component <VirtualListItem :component
props="{{virtualItem.props}}" offset="{{item.offset}}"
index="{{virtualItem.index}}" props="{{item.item.props}}"
key="{{virtualItem.key}}" index="{{item.item.index}}"
key="{{item.item.key}}"
/> />
{{/each}} {{/each}}
</div> </div>
@ -20,12 +21,25 @@
export default { export default {
oncreate() { oncreate() {
console.log('scrollHeight', this.refs.node.scrollHeight)
this.store.set({
scrollHeight: this.refs.node.scrollHeight,
})
this.observe('innerHeight', innerHeight => {
this.store.set({
innerHeight: innerHeight
})
})
this.observe('items', (items) => { this.observe('items', (items) => {
this.store.set({'items': items}) this.store.set({
'items': items
})
}) })
this.observe('scrollY', (scrollY) => { this.observe('scrollY', (scrollY) => {
console.log('scrollY', scrollY) console.log('scrollY', scrollY)
this.store.set({scrollTop: scrollY}) this.store.set({
scrollTop: scrollY
})
}) })
}, },
data: () => ({ data: () => ({

View file

@ -1,6 +1,6 @@
<div class="virtual-list-item" <div class="virtual-list-item"
ref:node ref:node
style="transform: translate3d(0, {{itemOffset}}px, 0);" style="transform: translate3d(0, {{offset}}px, 0);"
data-virtual-index="{{index}}" data-virtual-index="{{index}}"
data-virtual-key="{{key}}" data-virtual-key="{{key}}"
> >
@ -22,11 +22,6 @@
itemHeights[this.get('key')] = this.refs.node.offsetHeight itemHeights[this.get('key')] = this.refs.node.offsetHeight
this.store.set({itemHeights: itemHeights}) this.store.set({itemHeights: itemHeights})
}, },
computed: {
itemOffset: ($itemOffsets, key) => {
return $itemOffsets[key] || 0
}
},
store: () => virtualListStore store: () => virtualListStore
} }
</script> </script>

View file

@ -1,6 +1,8 @@
import { Store } from 'svelte/store.js' import { Store } from 'svelte/store.js'
import { splice } from 'svelte-extras' import { splice } from 'svelte-extras'
const RENDER_BUFFER = 1000
class VirtualListStore extends Store { class VirtualListStore extends Store {
} }
@ -9,7 +11,8 @@ VirtualListStore.prototype.splice = splice
const virtualListStore = new VirtualListStore({ const virtualListStore = new VirtualListStore({
items: [], items: [],
itemHeights: {}, itemHeights: {},
scrollTop: 0 scrollTop: 0,
scrollHeight: 0
}) })
virtualListStore.compute('virtualItems', ['items'], (items) => { virtualListStore.compute('virtualItems', ['items'], (items) => {
@ -20,15 +23,29 @@ virtualListStore.compute('virtualItems', ['items'], (items) => {
})) }))
}) })
virtualListStore.compute('itemOffsets', ['virtualItems', 'itemHeights'], (virtualItems, itemHeights) => { virtualListStore.compute('visibleItems',
let itemOffsets = {} ['virtualItems', 'scrollTop', 'height', 'itemHeights', 'innerHeight'],
let totalHeight = 0 (virtualItems, scrollTop, height, itemHeights, innerHeight) => {
let visibleItems = []
let currentOffset = 0
virtualItems.forEach(item => { virtualItems.forEach(item => {
let height = itemHeights[item.key] || 0 let height = itemHeights[item.key] || 0
itemOffsets[item.key] = totalHeight console.log(item.key, 'scrollTop', scrollTop, 'currentOffset', currentOffset, 'innerHeight', innerHeight)
totalHeight += height if (
((currentOffset < scrollTop) && (scrollTop - RENDER_BUFFER < currentOffset)) ||
((currentOffset >= scrollTop) && (currentOffset < (scrollTop + innerHeight + RENDER_BUFFER)))
) {
console.log(' rendering', item)
visibleItems.push({
item: item,
offset: currentOffset
})
} else {
console.log('not rendering', item)
}
currentOffset += height
}) })
return itemOffsets return visibleItems
}) })
virtualListStore.compute('height', ['virtualItems', 'itemHeights'], (virtualItems, itemHeights) => { virtualListStore.compute('height', ['virtualItems', 'itemHeights'], (virtualItems, itemHeights) => {