maintain first visible page

This commit is contained in:
Lu Wang 2013-11-17 17:44:29 +08:00
parent 920b693a06
commit c949183bca
2 changed files with 83 additions and 18 deletions

1
TODO
View File

@ -1,3 +1,4 @@
split js
position history stack (popstate)
scale limits
onresize

View File

@ -244,11 +244,20 @@ function Viewer(config) {
Viewer.prototype = {
scale : 1,
// index of the active page (most visible one)
/*
* index of the active page (the one with largest visible area)
* which estimates the page currently being viewed
*/
cur_page_idx : 0,
/*
* index of the first visible page
* used when determining current view
*/
first_page_idx : 0,
init_before_loading_content : function() {
/*hide all pages before loading, will reveal only visible ones later */
/* hide all pages before loading, will reveal only visible ones later */
this.pre_hide_pages();
},
@ -275,6 +284,8 @@ Viewer.prototype = {
}
this.find_pages();
// do nothing if there's nothing
if(this.pages.length == 0) return;
// disable dragging of background images
disable_dragstart(document.getElementsByClassName(CSS_CLASS_NAMES.background_image));
@ -293,6 +304,7 @@ Viewer.prototype = {
// register schedule rendering
// renew old schedules since scroll() may be called frequently
this.container.addEventListener('scroll', function() {
self.update_page_idx();
self.schedule_render(true);
}, false);
@ -434,7 +446,6 @@ Viewer.prototype = {
/*
* show visible pages and hide invisible pages
* update current page number
*/
render : function () {
var container = this.container;
@ -469,27 +480,80 @@ Viewer.prototype = {
} else {
this.load_page(i);
}
if (!cur_page_fully_visible) {
// check the visible fraction of the page
var page_visible_ratio = (Math.min(container_max_y, page_max_y) - Math.max(container_min_y, page_min_y)) / page_height;
if ((i === cur_page_idx) && (Math.abs(page_visible_ratio - 1.0) <= EPS)) {
cur_page_fully_visible = true;
} else if (page_visible_ratio > max_visible_ratio) {
max_visible_ratio = page_visible_ratio;
max_visible_page_idx = i;
}
}
} else {
cur_page.hide();
}
}
},
/*
* update cur_page_idx and first_page_idx
* normally called upon scrolling
*/
update_page_idx: function () {
var pages = this.pages;
var pages_len = pages.length;
// there is no chance that cur_page_idx or first_page_idx is modified
if (pages_len < 2) return;
var container = this.container;
var container_min_y = container.scrollTop;
var container_max_y = container_min_y + container.clientHeight;
// binary search for the first page
// whose bottom border is below the top border of the container
var first_idx = -1;
var last_idx = pages_len;
var rest_len = last_idx - first_idx;
// TODO: use current first_page_idx as a hint?
while(rest_len > 1) {
var idx = first_idx + Math.floor(rest_len / 2);
var cur_page_ele = pages[idx].page;
if (cur_page_ele.offsetTop + cur_page_ele.clientTop + cur_page_ele.clientHeight >= container_min_y) {
last_idx = idx;
} else {
first_idx = idx;
}
rest_len = last_idx - first_idx;
}
/*
* update current page number to the maximum visible page
* do not update it when current page is still fully visible
* with malformed settings it is possible that no page is visible, e.g.
* - the container is to thin, which lies in the margin between two pages
* - all pages are completely above or below the container
* but we just assume that they won't happen.
*/
if (!cur_page_fully_visible)
this.cur_page_idx = max_visible_page_idx;
this.first_page_idx = last_idx;
// find the page with largest visible area
var cur_page_idx = this.cur_page_idx;
var max_visible_page_idx = cur_page_idx;
var max_visible_ratio = 0.0;
for(var i = last_idx; i < pages_len; ++i) {
var cur_page_ele = pages[i].page;
var page_min_y = cur_page_ele.offsetTop + cur_page_ele.clientTop;
var page_height = cur_page_ele.clientHeight;
var page_max_y = page_min_y + page_height;
if (page_min_y > container_max_y) break;
// check the visible fraction of the page
var page_visible_ratio = ( Math.min(container_max_y, page_max_y)
- Math.max(container_min_y, page_min_y)
) / page_height;
// stay with the current page if it is still fully visible
if ((i === cur_page_idx) && (Math.abs(page_visible_ratio - 1.0) <= EPS)) {
max_visible_page_idx = cur_page_idx;
break;
}
if (page_visible_ratio > max_visible_ratio) {
max_visible_ratio = page_visible_ratio;
max_visible_page_idx = i;
}
}
this.cur_page_idx = max_visible_page_idx;
},
/**