mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Merge pull request #142 from sharelatex/pdfng-scrollhandler
Pdfng scrollhandler performance improvements
This commit is contained in:
commit
e66cd6dc58
3 changed files with 117 additions and 83 deletions
|
@ -29,59 +29,36 @@ define [
|
|||
canvasElement.width(w)
|
||||
scope.page.sized = true
|
||||
|
||||
isVisible = (containerSize) ->
|
||||
elemTop = element.offset().top - containerSize[2]
|
||||
elemBottom = elemTop + element.innerHeight()
|
||||
visible = (elemTop < containerSize[1] and elemBottom > 0)
|
||||
scope.page.visible = visible
|
||||
scope.page.elemTop = elemTop
|
||||
scope.page.elemBottom = elemBottom
|
||||
return visible
|
||||
|
||||
renderPage = () ->
|
||||
scope.document.renderPage {
|
||||
# keep track of our page element, so we can access it in the
|
||||
# parent with scope.pages[i].element, and the contained
|
||||
# elements for each part
|
||||
scope.page.element = element
|
||||
scope.page.elementChildren = {
|
||||
canvas: canvasElement,
|
||||
text: textElement
|
||||
annotations: annotationsElement
|
||||
highlights: highlightsElement
|
||||
}, scope.page.pageNum
|
||||
container: element
|
||||
}
|
||||
|
||||
pausePage = () ->
|
||||
scope.document.pause {
|
||||
canvas: canvasElement,
|
||||
text: textElement
|
||||
}, scope.page.pageNum
|
||||
|
||||
# keep track of our page element, so we can access it in the
|
||||
# parent with scope.pages[i].element
|
||||
scope.page.element = element
|
||||
|
||||
if (!scope.page.sized && scope.defaultPageSize)
|
||||
if !scope.page.sized
|
||||
if scope.defaultPageSize?
|
||||
updatePageSize scope.defaultPageSize
|
||||
else
|
||||
# shouldn't get here - the default page size should now
|
||||
# always be set before redraw is called
|
||||
handler = scope.$watch 'defaultPageSize', (defaultPageSize) ->
|
||||
return unless defaultPageSize?
|
||||
updatePageSize defaultPageSize
|
||||
handler()
|
||||
|
||||
if scope.page.current
|
||||
# console.log 'we must scroll to this page', scope.page.pageNum, 'at position', scope.page.position
|
||||
renderPage()
|
||||
# this is the current page, we want to scroll it into view
|
||||
# and render it immediately
|
||||
scope.document.renderPage scope.page
|
||||
ctrl.setPdfPosition(scope.page, scope.page.position)
|
||||
|
||||
scope.$watch 'defaultPageSize', (defaultPageSize) ->
|
||||
return unless defaultPageSize?
|
||||
updatePageSize defaultPageSize
|
||||
|
||||
watchHandle = scope.$watch 'containerSize', (containerSize, oldVal) ->
|
||||
return unless containerSize?
|
||||
return unless scope.page.sized
|
||||
oldVisible = scope.page.visible
|
||||
newVisible = isVisible containerSize
|
||||
scope.page.visible = newVisible
|
||||
if newVisible && !oldVisible
|
||||
renderPage()
|
||||
# TODO deregister this listener after the page is rendered
|
||||
#watchHandle()
|
||||
else if !newVisible && oldVisible
|
||||
pausePage()
|
||||
|
||||
element.on 'dblclick', (e) ->
|
||||
offset = $(element).find('.pdf-canvas').offset()
|
||||
dx = e.pageX - offset.left
|
||||
|
@ -99,7 +76,7 @@ define [
|
|||
highlights: highlightsElement
|
||||
})
|
||||
|
||||
scope.$watch 'highlights', (highlights, oldVal) ->
|
||||
scope.$on 'pdf:highlights', (event, highlights) ->
|
||||
return unless highlights?
|
||||
return unless highlights.length > 0
|
||||
if scope.timeoutHandler
|
||||
|
|
|
@ -25,6 +25,7 @@ define [
|
|||
pdfDocument.getDownloadInfo().then () =>
|
||||
@options.loadedCallback()
|
||||
@errorCallback = @options.errorCallback
|
||||
@pageSizeChangeCallback = @options.pageSizeChangeCallback
|
||||
@pdfjs.catch (exception) =>
|
||||
# console.log 'ERROR in get document', exception
|
||||
@errorCallback(exception)
|
||||
|
@ -89,13 +90,6 @@ define [
|
|||
setScale: (@scale) ->
|
||||
@resetState()
|
||||
|
||||
pause: (element, pagenum) ->
|
||||
return if @complete[pagenum]
|
||||
return if @shuttingDown
|
||||
@renderQueue = @renderQueue.filter (q) ->
|
||||
q.pagenum != pagenum
|
||||
@spinner.stop(element.canvas)
|
||||
|
||||
triggerRenderQueue: (interval = @JOB_QUEUE_INTERVAL) ->
|
||||
$timeout () =>
|
||||
@processRenderQueue()
|
||||
|
@ -107,14 +101,23 @@ define [
|
|||
@jobs = @jobs - 1
|
||||
@triggerRenderQueue(0)
|
||||
|
||||
renderPage: (element, pagenum) ->
|
||||
renderPages: (pages) ->
|
||||
return if @shuttingDown
|
||||
@renderQueue = for page in pages
|
||||
{
|
||||
'element': page.elementChildren
|
||||
'pagenum': page.pageNum
|
||||
}
|
||||
@triggerRenderQueue()
|
||||
|
||||
renderPage: (page) ->
|
||||
return if @shuttingDown
|
||||
current = {
|
||||
'element': element
|
||||
'pagenum': pagenum
|
||||
'element': page.elementChildren
|
||||
'pagenum': page.pageNum
|
||||
}
|
||||
@renderQueue.push(current)
|
||||
@triggerRenderQueue()
|
||||
@renderQueue.push current
|
||||
@processRenderQueue()
|
||||
|
||||
processRenderQueue: () ->
|
||||
return if @shuttingDown
|
||||
|
@ -131,7 +134,9 @@ define [
|
|||
@jobs = @jobs + 1
|
||||
|
||||
element.canvas.addClass('pdfng-loading')
|
||||
spinTimer = $timeout () =>
|
||||
@spinner.add(element.canvas)
|
||||
, 100
|
||||
|
||||
completeRef = @complete
|
||||
renderTaskRef = @renderTask
|
||||
|
@ -142,6 +147,7 @@ define [
|
|||
Raven.captureMessage?('pdfng page load timed out after ' + @PAGE_LOAD_TIMEOUT + 'ms')
|
||||
# console.log 'page load timed out', pagenum
|
||||
timedOut = true
|
||||
$timeout.cancel(spinTimer)
|
||||
@spinner.stop(element.canvas)
|
||||
# @jobs = @jobs - 1
|
||||
# @triggerRenderQueue(0)
|
||||
|
@ -153,6 +159,7 @@ define [
|
|||
@pageLoad[pagenum].then (pageObject) =>
|
||||
# console.log 'in page load success', pagenum
|
||||
$timeout.cancel(timer)
|
||||
$timeout.cancel(spinTimer)
|
||||
@renderTask[pagenum] = @doRender element, pagenum, pageObject
|
||||
@renderTask[pagenum].then () =>
|
||||
# complete
|
||||
|
@ -166,6 +173,7 @@ define [
|
|||
.catch (error) ->
|
||||
# console.log 'in page load error', pagenum, 'timedOut=', timedOut
|
||||
$timeout.cancel(timer)
|
||||
$timeout.cancel(spinTimer)
|
||||
# console.log 'ERROR', error
|
||||
|
||||
doRender: (element, pagenum, page) ->
|
||||
|
@ -202,8 +210,14 @@ define [
|
|||
canvas.height(newHeight + 'px')
|
||||
canvas.width(newWidth + 'px')
|
||||
|
||||
element.canvas.height(newHeight)
|
||||
element.canvas.width(newWidth)
|
||||
oldHeight = element.canvas.height()
|
||||
oldWidth = element.canvas.width()
|
||||
if newHeight != oldHeight or newWidth != oldWidth
|
||||
element.canvas.height(newHeight + 'px')
|
||||
element.canvas.width(newWidth + 'px')
|
||||
element.container.height(newHeight + 'px')
|
||||
element.container.width(newWidth + 'px')
|
||||
@pageSizeChangeCallback?(pagenum, newHeight - oldHeight)
|
||||
|
||||
if pixelRatio != 1
|
||||
ctx.scale(pixelRatio, pixelRatio)
|
||||
|
|
|
@ -40,6 +40,8 @@ define [
|
|||
errorCallback: (error) ->
|
||||
Raven.captureMessage?('pdfng error ' + error)
|
||||
$scope.$emit 'pdf:error', error
|
||||
pageSizeChangeCallback: (pageNum, deltaH) ->
|
||||
$scope.$broadcast 'pdf:page:size-change', pageNum, deltaH
|
||||
})
|
||||
|
||||
# we will have all the main information needed to start display
|
||||
|
@ -144,18 +146,18 @@ define [
|
|||
# find first visible page
|
||||
visible = $scope.pages.some (page, i) ->
|
||||
[topPageIdx, topPage] = [i, page] if page.visible
|
||||
if visible
|
||||
if visible && topPage.element?
|
||||
# console.log 'found it', topPageIdx
|
||||
else
|
||||
# console.log 'CANNOT FIND TOP PAGE'
|
||||
return
|
||||
|
||||
# console.log 'top page is', topPage.pageNum, topPage.elemTop, topPage.elemBottom, topPage
|
||||
top = topPage.elemTop
|
||||
bottom = topPage.elemBottom
|
||||
viewportTop = 0
|
||||
viewportHeight = $element.height()
|
||||
topVisible = (top >= viewportTop && top < viewportTop + viewportHeight)
|
||||
top = topPage.element.offset().top
|
||||
bottom = top + topPage.element.innerHeight()
|
||||
viewportTop = $element.offset().top
|
||||
viewportBottom = viewportTop + $element.height()
|
||||
topVisible = (top >= viewportTop && top < viewportBottom)
|
||||
someContentVisible = (top < viewportTop && bottom > viewportTop)
|
||||
# console.log 'in PdfListView', top, topVisible, someContentVisible, viewportTop
|
||||
if topVisible
|
||||
|
@ -237,13 +239,39 @@ define [
|
|||
layoutReady.promise.then () ->
|
||||
# console.log 'layoutReady was resolved'
|
||||
|
||||
# TODO can we combine this with scope.parentSize, need to finalize boxes
|
||||
updateContainer = () ->
|
||||
scope.containerSize = [
|
||||
element.innerWidth()
|
||||
element.innerHeight()
|
||||
element.offset().top
|
||||
]
|
||||
renderVisiblePages = () ->
|
||||
pages = getVisiblePages()
|
||||
# pages = getExtraPages visiblePages
|
||||
scope.document.renderPages(pages)
|
||||
|
||||
getVisiblePages = () ->
|
||||
top = element[0].scrollTop;
|
||||
bottom = top + element[0].clientHeight;
|
||||
visiblePages = scope.pages.filter (page) ->
|
||||
pageElement = page.element[0]
|
||||
pageTop = pageElement.offsetTop
|
||||
pageBottom = pageTop + pageElement.clientHeight
|
||||
page.visible = pageTop < bottom and pageBottom > top
|
||||
return page.visible
|
||||
return visiblePages
|
||||
|
||||
getExtraPages = (visiblePages) ->
|
||||
extra = []
|
||||
firstVisiblePage = visiblePages[0].pageNum
|
||||
firstVisiblePageIdx = firstVisiblePage - 1
|
||||
len = visiblePages.length
|
||||
lastVisiblePage = visiblePages[len-1].pageNum
|
||||
lastVisiblePageIdx = lastVisiblePage - 1
|
||||
# first page after
|
||||
if lastVisiblePageIdx + 1 < scope.pages.length
|
||||
extra.push scope.pages[lastVisiblePageIdx + 1]
|
||||
# page before
|
||||
if firstVisiblePageIdx > 0
|
||||
extra.push scope.pages[firstVisiblePageIdx - 1]
|
||||
# second page after
|
||||
if lastVisiblePageIdx + 2 < scope.pages.length
|
||||
extra.push scope.pages[lastVisiblePageIdx + 2]
|
||||
return visiblePages.concat extra
|
||||
|
||||
doRescale = (scale) ->
|
||||
# console.log 'doRescale', scale
|
||||
|
@ -255,6 +283,7 @@ define [
|
|||
ctrl.setScale(scale, h, w).then () ->
|
||||
spinner.remove(element)
|
||||
ctrl.redraw(origposition)
|
||||
setTimeout renderVisiblePages, 0
|
||||
|
||||
checkElementReady = () ->
|
||||
# if element is zero-sized keep checking until it is ready
|
||||
|
@ -270,7 +299,7 @@ define [
|
|||
scope.$on 'layout-ready', () ->
|
||||
# console.log 'GOT LAYOUT READY EVENT'
|
||||
# console.log 'calling refresh'
|
||||
updateContainer()
|
||||
# updateContainer()
|
||||
spinner.add(element)
|
||||
layoutReady.resolve 'layout is ready'
|
||||
scope.parentSize = [
|
||||
|
@ -307,26 +336,38 @@ define [
|
|||
# trigger a redraw
|
||||
scope.scale = angular.copy (scope.scale)
|
||||
|
||||
scope.$on 'pdf:page:size-change', (event, pageNum, delta) ->
|
||||
#console.log 'page size change event', pageNum, delta
|
||||
origposition = angular.copy scope.position
|
||||
#console.log 'orig position', JSON.stringify(origposition)
|
||||
if pageNum - 1 < origposition.page && delta != 0
|
||||
currentScrollTop = element.scrollTop()
|
||||
#console.log 'adjusting scroll from', currentScrollTop, 'by', delta
|
||||
scope.adjustingScroll = true
|
||||
element.scrollTop(currentScrollTop + delta)
|
||||
|
||||
element.on 'scroll', () ->
|
||||
#console.log 'scroll event', element.scrollTop(), 'adjusting?', scope.adjustingScroll
|
||||
#scope.scrollPosition = element.scrollTop()
|
||||
if scope.adjustingScroll
|
||||
updateContainer()
|
||||
renderVisiblePages()
|
||||
# updateContainer()
|
||||
scope.$apply()
|
||||
scope.adjustingScroll = false
|
||||
return
|
||||
scope.scrolled = true
|
||||
#scope.scrolled = true
|
||||
if scope.scrollHandlerTimeout
|
||||
$timeout.cancel(scope.scrollHandlerTimeout)
|
||||
scope.scrollHandlerTimeout = $timeout scrollHandler, 100
|
||||
clearTimeout(scope.scrollHandlerTimeout)
|
||||
scope.scrollHandlerTimeout = setTimeout scrollHandler, 25
|
||||
|
||||
scrollHandler = () ->
|
||||
scope.scrollHandlerTimeout = null
|
||||
updateContainer()
|
||||
scope.$apply()
|
||||
renderVisiblePages()
|
||||
#scope.$apply()
|
||||
newPosition = ctrl.getPdfPosition()
|
||||
if newPosition?
|
||||
scope.position = newPosition
|
||||
scope.$apply()
|
||||
#scope.$apply()
|
||||
scope.scrollHandlerTimeout = null
|
||||
|
||||
scope.$watch 'pdfSrc', (newVal, oldVal) ->
|
||||
# console.log 'loading pdf', newVal, oldVal
|
||||
|
@ -421,6 +462,8 @@ define [
|
|||
|
||||
return if !highlights.length
|
||||
|
||||
scope.$broadcast 'pdf:highlights', areas
|
||||
|
||||
first = highlights[0]
|
||||
|
||||
pageNum = scope.pages[first.page].pageNum
|
||||
|
|
Loading…
Reference in a new issue