Я пытаюсь создать epub-ридер для Android, все прекрасно и работает, как ожидалось, НО проблема, которую я не могу решить, - это сохранение последней просмотренной страницы (или сохранение позиции для закладки).
Немного фона:
Я использую css multi column
, чтобы показать epub, columnWidth
установлен на windowWidth
, а columnHeight
установлен на windowHeight
.
Чтобы каждый столбец заполнил весь экран.
В настоящее время для сохранения позиции я предварительно обрабатываю html и обертываю каждый элемент с помощью div
, включая конкретный id
, который представляет номер раздела и позицию тега. Например, тег <p>
после процесса будет выглядеть следующим образом:
<div id="id__1__8"><p>some text</p></div>
id__1__8
означает, что этот текст относится к разделу 1, и это 8-й элемент в этом теле.
У меня есть полный список этих идентификаторов, и для сохранения позиции я использую jQuery для сравнения слева от текущего столбца слева от каждого id
, поэтому ближайший id
будет найден, и я знаю, что эта страница принадлежит где в epub.
Следующий шаг - найти смещение (предположим, тег p
, который заполняет 7 страниц). Со смещением я знаю, что я должен загрузить восьмой элемент раздела 1 и перейти на страницу 5.
Посмотрите на функцию в jQuery: (для поиска ближайшего элемента и смещения)
jqGetLastPosition = function(ids)
{
var tempColumn = _column; // _column is current page that is showing
if(tempColumn < 0)
{
tempColumn = -1 * tempColumn;
}
var realIds = ids.split("|");
var columnLeft = (tempColumn * (_windowWidth + _columnGap));
var currentLeft;
var currId = "#" + realIds[0];
var nearestId = realIds[0] + "__0";
var minDistance = 1000000;
var tempDistance = 0;
var exactColumn = 0;
for(i=0; i<realIds.length; i++)
{
try
{
currId = "#" + realIds[i];
currentLeft = $(currId).position().left;
if(currentLeft < 0)
{
currentLeft = -1 * currentLeft;
}
tempDistance = columnLeft - currentLeft;
if(tempDistance < 0)
{
//this id is after this page
continue;
}
else if(tempDistance < minDistance)
{
minDistance = tempDistance;
exactColumn = Math.floor(minDistance/(_windowWidth + _columnGap)); //this must compute the offset pages after nearest element
nearestId = realIds[i] + "__" + exactColumn;
}
}
catch(e)
{
}
}
jsSaveLastLocation(nearestId);
};
Этот код отлично подходит для большинства ситуаций, когда смещение страницы ноль, например id__1__8__0
.
Проблема возникает, когда есть смещение, страница смещения не может быть вычислена правильно, я вижу, что есть одно смещение страницы, но этот код дает мне 0, или когда есть 9-страничное смещение, это дает мне 4.
В чем проблема с этим кодом?
Или я ошибаюсь, делая это для сохранения местоположения?
Есть ли лучший способ?
UPDATE:
Если я добавлю div
перед тем, как любой тег, например <div id="id__1__8"></div><p>some text</p>
, результат будет точным в 90% случаев. поэтому обновленный вопрос будет Как достичь этой цели (сохранение позиции в epub) со 100-процентной точностью?
ОБНОВЛЕНИЕ 2:
Я помещаю div
для каждого элемента, например. head
, p
, link
, img
....
Есть ли какая-то возможность, что это создает проблему?
ОБНОВЛЕНИЕ 3:
Наконец-то я обнаружил, что вызывает проблему. рассмотрите ситуацию, когда ближайший элемент к текущей странице начинается в середине предыдущей страницы, я сохраняю идентификатор этого элемента, и смещение будет равным 1. Когда я хочу загрузить сохраненное местоположение, загрузка элемента вверху page, SO немного изменится в тексте, в приведенном ниже изображении я покажу, что происходит.
любая идея будет оценена
ОБНОВЛЕНИЕ 4:
CSS
#container {
width: 100%;
height: 98%;
overflow: hidden;
}
#content {
position: relative;
height: 98%;
-moz-column-width: 200px;
-webkit-column-width: 200px;
column-width: 200px;
-moz-column-gap: 1px;
-webkit-column-gap: 1px;
column-gap: 1px;
}
img {
max-width: 100%;
max-height: 100%;
display:inline-block;
-webkit-column-break-inside : avoid;
}
<span id=\"endMarker\"></span>
добавит к концу тела, поэтому у меня есть маркер в конце содержимого html.
JQuery:
var _column = 0;
var _columnCount = 0;
var _windowWidth;
var _windowHeight;
var rtl = 0;
$(function() {
_columnWidth = $('#container').width();
_windowWidth = $('#container').width();
_windowHeight = $('#container').height();
$('#content').css('-webkit-column-width', _windowWidth);
$('#content').css('-moz-column-width', _windowWidth);
$('#content').css('column-width', _windowWidth);
$(document).ready(function(){
$(window).load(function(){
_columnCount = Math.floor($('#endMarker').position().left/(_windowWidth + _columnGap));
if(_columnCount < 0)
{
rtl = 1;
_columnCount = (_columnCount * -1);// + 2;
informRTL(rtl); //inform the java part that this doc is right to left
}
else
{
informRTL(rtl);
}
reportNumberOfPage(_columnCount); // this will report to java part
});
});
setColumn = function(i) {
if(rtl == 1)
{
_column = (i * -1);
}
else
{
_column = i;
}
$('#content').css({"-webkit-transform":"translate(" + (-1 * _column * (_windowWidth + _columnGap)) + "px,0px)"});
}
setColumn(0); //set the showing column to first
nextPage = function() {
if (_column==_columnCount -1 || (-1*_column)==_columnCount -1)
informEndPage();
else
{
if(rtl == 1)
{
_column = _column-1;
$('#content').css({"-webkit-transform":"translate(" + (-1 * _column * (_windowWidth + _columnGap)) + "px,0px)"});
}
else
{
_column = _column+1;
$('#content').css({"-webkit-transform":"translate(" + (-1 * _column * (_windowWidth + _columnGap)) + "px,0px)"});
}
}
};
prevPage = function() {
if (0==_column)
informStartPage();
else
{
if(rtl == 1)
{
_column = _column+1;
$('#content').css({"-webkit-transform":"translate(" + (-1 * _column * (_windowWidth + _columnGap)) + "px,0px)"});
updateCurrentPageText((_column * -1));
}
else
{
_column = _column-1;
$('#content').css({"-webkit-transform":"translate(" + (-1 * _column * (_windowWidth + _columnGap)) + "px,0px)"});
updateCurrentPageText(_column);
}
}
};
//this function add more html content to the end of current body
addString = function(s)
{
$(s).insertBefore('#endMarker');
$(window).load(addStringReport());
};
addStringReport = function()
{
_columnCount = Math.floor($('#endMarker').position().left/(_windowWidth + _columnGap));
if(_columnCount == 0)
{
requestMorePage();
}
if(_columnCount < 0)
{
rtl = 1;
_columnCount = (_columnCount * -1);
}
nextPage();
reportNumberOfPage(_columnCount);
}
//this function add more html content to the first of body
addStringToFirst = function(s)
{
$('#content').prepend(s);
$(window).load(addStringToFirstReport());
}
addStringToFirstReport = function()
{
maxColumn = Math.floor($('#endMarker').position().left/(_windowWidth + _columnGap));
if(maxColumn < 0)
{
rtl = 1;
maxColumn = (maxColumn * -1);
_column = (maxColumn - _columnCount + _column);
}
else
{
_column = maxColumn - _columnCount + _column;
}
_columnCount = maxColumn;
setColumn(_column);
reportNumberOfPage(_columnCount);
}
это почти весь мой код, если вам нужно больше, пожалуйста, дайте мне знать.