calculate listOffset to avoid profile offset issue
This commit is contained in:
parent
98b8ea1c67
commit
ef51842e6a
|
@ -1,5 +1,7 @@
|
||||||
<VirtualListContainer :realm :containerQuery >
|
<VirtualListContainer :realm :containerQuery >
|
||||||
<div class="virtual-list {{shown ? '' : 'hidden'}}" style="height: {{$height}}px;">
|
<div class="virtual-list {{shown ? '' : 'hidden'}}"
|
||||||
|
style="height: {{$height}}px;"
|
||||||
|
ref:node >
|
||||||
<VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/>
|
<VirtualListHeader component="{{headerComponent}}" virtualProps="{{headerProps}}" shown="{{$showHeader}}"/>
|
||||||
{{#if $visibleItems}}
|
{{#if $visibleItems}}
|
||||||
{{#each $visibleItems as visibleItem @key}}
|
{{#each $visibleItems as visibleItem @key}}
|
||||||
|
@ -85,6 +87,7 @@
|
||||||
if (scrollTop === 0) {
|
if (scrollTop === 0) {
|
||||||
this.fireScrollToTop()
|
this.fireScrollToTop()
|
||||||
}
|
}
|
||||||
|
this.calculateListOffset()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
@ -104,6 +107,19 @@
|
||||||
scrollTop: ($scrollTop) => $scrollTop,
|
scrollTop: ($scrollTop) => $scrollTop,
|
||||||
// TODO: bug in svelte store, shouldn't need to do this
|
// TODO: bug in svelte store, shouldn't need to do this
|
||||||
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight,
|
allVisibleItemsHaveHeight: ($allVisibleItemsHaveHeight) => $allVisibleItemsHaveHeight,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calculateListOffset() {
|
||||||
|
// TODO: better way to get the offset top?
|
||||||
|
let node = this.refs.node
|
||||||
|
if (!node) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mark('calculateListOffset')
|
||||||
|
let listOffset = node.offsetParent.offsetTop
|
||||||
|
this.store.setForRealm({listOffset})
|
||||||
|
stop('calculateListOffset')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
|
@ -2,7 +2,7 @@ import { mark, stop } from '../../_utils/marks'
|
||||||
import { RealmStore } from '../../_utils/RealmStore'
|
import { RealmStore } from '../../_utils/RealmStore'
|
||||||
import { reselect } from '../../_utils/reselect'
|
import { reselect } from '../../_utils/reselect'
|
||||||
|
|
||||||
const RENDER_BUFFER_FACTOR = 5
|
const RENDER_BUFFER_FACTOR = 1.5
|
||||||
|
|
||||||
class VirtualListStore extends RealmStore {
|
class VirtualListStore extends RealmStore {
|
||||||
constructor (state) {
|
constructor (state) {
|
||||||
|
@ -20,16 +20,18 @@ virtualListStore.computeForRealm('headerHeight', 0)
|
||||||
virtualListStore.computeForRealm('scrollTop', 0)
|
virtualListStore.computeForRealm('scrollTop', 0)
|
||||||
virtualListStore.computeForRealm('scrollHeight', 0)
|
virtualListStore.computeForRealm('scrollHeight', 0)
|
||||||
virtualListStore.computeForRealm('offsetHeight', 0)
|
virtualListStore.computeForRealm('offsetHeight', 0)
|
||||||
|
virtualListStore.computeForRealm('listOffset', 0)
|
||||||
virtualListStore.computeForRealm('itemHeights', {})
|
virtualListStore.computeForRealm('itemHeights', {})
|
||||||
|
|
||||||
virtualListStore.compute('rawVisibleItems',
|
virtualListStore.compute('rawVisibleItems',
|
||||||
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'showHeader', 'headerHeight'],
|
['items', 'scrollTop', 'itemHeights', 'offsetHeight', 'showHeader', 'headerHeight', 'listOffset'],
|
||||||
(items, scrollTop, itemHeights, offsetHeight, showHeader, headerHeight) => {
|
(items, scrollTop, itemHeights, offsetHeight, showHeader, headerHeight, listOffset) => {
|
||||||
window.rawVisibleItemsComputed = (window.rawVisibleItemsComputed || 0) + 1
|
window.rawVisibleItemsComputed = (window.rawVisibleItemsComputed || 0) + 1
|
||||||
mark('compute visibleItems')
|
mark('compute visibleItems')
|
||||||
if (!items) {
|
if (!items) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
let effectiveScrollTop = scrollTop - listOffset
|
||||||
let renderBuffer = RENDER_BUFFER_FACTOR * offsetHeight
|
let renderBuffer = RENDER_BUFFER_FACTOR * offsetHeight
|
||||||
let visibleItems = []
|
let visibleItems = []
|
||||||
let totalOffset = showHeader ? headerHeight : 0
|
let totalOffset = showHeader ? headerHeight : 0
|
||||||
|
@ -40,13 +42,13 @@ virtualListStore.compute('rawVisibleItems',
|
||||||
let height = itemHeights[key] || 0
|
let height = itemHeights[key] || 0
|
||||||
let currentOffset = totalOffset
|
let currentOffset = totalOffset
|
||||||
totalOffset += height
|
totalOffset += height
|
||||||
let isAboveViewport = (currentOffset < scrollTop)
|
let isAboveViewport = (currentOffset < effectiveScrollTop)
|
||||||
if (isAboveViewport) {
|
if (isAboveViewport) {
|
||||||
if ((scrollTop - height - renderBuffer) > currentOffset) {
|
if ((effectiveScrollTop - height - renderBuffer) > currentOffset) {
|
||||||
continue // above the area we want to render
|
continue // above the area we want to render
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (currentOffset > (scrollTop + offsetHeight + renderBuffer)) {
|
if (currentOffset > (effectiveScrollTop + offsetHeight + renderBuffer)) {
|
||||||
break // below the area we want to render
|
break // below the area we want to render
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
export default {
|
export default {
|
||||||
oncreate() {
|
oncreate() {
|
||||||
let accountId = this.get('params').accountId
|
let accountId = this.get('params').accountId
|
||||||
let instanceName = this.store.get('currentInstance')
|
|
||||||
updateProfileAndRelationship(accountId)
|
updateProfileAndRelationship(accountId)
|
||||||
},
|
},
|
||||||
store: () => store,
|
store: () => store,
|
||||||
|
|
|
@ -3,16 +3,20 @@
|
||||||
|
|
||||||
let hasBoundingRectBug
|
let hasBoundingRectBug
|
||||||
|
|
||||||
|
function rectsAreEqual (rectA, rectB) {
|
||||||
|
return rectA.height === rectB.height &&
|
||||||
|
rectA.top === rectB.top &&
|
||||||
|
rectA.width === rectB.width &&
|
||||||
|
rectA.bottom === rectB.bottom &&
|
||||||
|
rectA.left === rectB.left &&
|
||||||
|
rectA.right === rectB.right
|
||||||
|
}
|
||||||
|
|
||||||
export function getRectFromEntry (entry) {
|
export function getRectFromEntry (entry) {
|
||||||
if (typeof hasBoundingRectBug !== 'boolean') {
|
if (typeof hasBoundingRectBug !== 'boolean') {
|
||||||
const boundingRect = entry.target.getBoundingClientRect()
|
const boundingRect = entry.target.getBoundingClientRect()
|
||||||
const observerRect = entry.boundingClientRect
|
const observerRect = entry.boundingClientRect
|
||||||
hasBoundingRectBug = boundingRect.height !== observerRect.height ||
|
hasBoundingRectBug = !rectsAreEqual(boundingRect, observerRect)
|
||||||
boundingRect.top !== observerRect.top ||
|
|
||||||
boundingRect.width !== observerRect.width ||
|
|
||||||
boundingRect.bottom !== observerRect.bottom ||
|
|
||||||
boundingRect.left !== observerRect.left ||
|
|
||||||
boundingRect.right !== observerRect.right
|
|
||||||
}
|
}
|
||||||
return hasBoundingRectBug ? entry.target.getBoundingClientRect() : entry.boundingClientRect
|
return hasBoundingRectBug ? entry.target.getBoundingClientRect() : entry.boundingClientRect
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue