Skip to content

Commit

Permalink
New: Improved touch screen navigation (swipe gesture, 2 finger zoom a…
Browse files Browse the repository at this point in the history
…nd reset zoom with 2 finger click)
  • Loading branch information
ollm committed Oct 15, 2023
1 parent ff9a96b commit f848463
Show file tree
Hide file tree
Showing 4 changed files with 249 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- Option to start OpenComic directly in last reading [`00cb8c7`](https://github.com/ollm/OpenComic/commit/00cb8c7da9eb8345aaec8faa3b5c91953c2350dd)
- Recently opened page [`d2f3065`](https://github.com/ollm/OpenComic/commit/d2f30653f506993a45e49ad5e7e5e8434c33a9be)
- Option to move zoom and scroll whit mouse [`e8cc79c`](https://github.com/ollm/OpenComic/commit/e8cc79cbddd23ff7d47b7046190cecbad199d3c2)
- Improved touch screen navigation (swipe gesture, 2 finger zoom and reset zoom with 2 finger click)

##### 🐛 Bug Fixes

Expand Down
34 changes: 34 additions & 0 deletions scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,37 @@ function clientX(e) {

}

function touchesXY(e)
{
let touches = [];

for(let i = 0, len = e.touches.length; i < len; i++)
{
touches.push(e.touches[i].pageX);
touches.push(e.touches[i].pageY);
}

return touches;
}

function touchesDiff(touches0, touches1)
{
let touches = [];

for(let i = 0, len = touches0.length; i < len; i++)
{
if(touches1[i] !== undefined)
touches.push(Math.abs(touches0[i] - touches1[i]));
}

return touches;
}

function distance(x1, y1, x2, y2)
{
return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2);
}

function rand(min = 0, max = 10000000)
{
return Math.floor(Math.random() * (max - min + 1)) + min;
Expand Down Expand Up @@ -176,6 +207,9 @@ module.exports = {
pageX: pageX,
clientY: clientY,
clientX: clientX,
touchesXY: touchesXY,
touchesDiff: touchesDiff,
distance: distance,
rand: rand,
sleep: sleep,
setImmediate: setImmediate,
Expand Down
243 changes: 212 additions & 31 deletions scripts/reading.js
Original file line number Diff line number Diff line change
Expand Up @@ -1453,11 +1453,6 @@ function showPreviousComic(mode, animation = true, invert = false)

var currentScale = 1, scalePrevData = {tranX: 0, tranX2: 0, tranY: 0, tranY2: 0, scale: 1, scrollTop: 0}, originalRect = false, originalRectReadingBody = false, originalRect2 = false, originalRectReadingBody2 = false, haveZoom = false, currentZoomIndex = false, applyScaleST = false, zoomingIn = false, prevAnime = false;

function applyScaleScrollAndHeight()
{

}

function applyScale(animation = true, scale = 1, center = false, zoomOut = false, round = true)
{
let animationDurationS = ((animation) ? _config.readingViewSpeed : 0);
Expand Down Expand Up @@ -3153,7 +3148,7 @@ function eachImagesDistribution(index, contains, callback, first = false, notFou

// Events functions

var contentLeftRect = false, barHeaderRect = false;
var contentLeftRect = false, contentRightRect = false, barHeaderRect = false, touchevents = {active: false, start: false, distance: 0, scale: 0, maxTouches: 0, numTouches: 0, touches: [], touchesXY: [], type: 'move'};

function mousemove(event)
{
Expand All @@ -3167,20 +3162,32 @@ function mousemove(event)

if(haveZoom) // Drag Image zoom
{
if(config.readingMoveZoomWithMouse && (!readingViewIs('scroll') || config.readingScrollWithMouse) && !(event instanceof PointerEvent))
if(contentRightRect === false)
{
event.preventDefault();
contentRightRect = template._contentRight().getBoundingClientRect();
let _contentRightRect = template._contentRight().firstElementChild.firstElementChild.getBoundingClientRect();
contentRightRect.width = _contentRightRect.width;
}

let x = -(pageX - zoomMoveData.x) * (scalePrevData.scale - 0.8);
let y = -(pageY - zoomMoveData.y) * (scalePrevData.scale - 0.8);
if(config.readingMoveZoomWithMouse && (!readingViewIs('scroll') || config.readingScrollWithMouse) && event instanceof MouseEvent)
{
if(pageX > contentRightRect.left && pageY > contentRightRect.top)
{
event.preventDefault();

dragZoom(x, y);
let _pageX = pageX - contentRightRect.left;
let _pageY = pageY - contentRightRect.top;

scalePrevData.tranX = zoomMoveData.tranX;
scalePrevData.tranY = zoomMoveData.tranY;
let x = -(_pageX - contentRightRect.width / 2) * (scalePrevData.scale - 1);
let y = -(_pageY - contentRightRect.height / 2) * (scalePrevData.scale - 1);

dragZoom(x - scalePrevData.tranX2, y - scalePrevData.tranY2);

scalePrevData.tranX = zoomMoveData.tranX;
scalePrevData.tranY = zoomMoveData.tranY;
}
}
else if(zoomMoveData.active)
else if(zoomMoveData.active && !(event instanceof TouchEvent))
{
event.preventDefault();

Expand All @@ -3191,6 +3198,108 @@ function mousemove(event)
}
}

if(touchevents.active && event instanceof TouchEvent)
{
let touches = event.touches;

// Simulate touch with 2 fingers
if(event.ctrlKey)
touches = [event.touches[0], touchevents.touches[1] || touchevents.touches[0]];

let numTouches = touches.length;

if(numTouches > touchevents.maxTouches)
touchevents.maxTouches = numTouches;

if(!touchevents.start)
{
let touchesXY = app.touchesXY(event);
let maxDiff = Math.max(...app.touchesDiff(touchevents.touchesXY, touchesXY));

if(maxDiff > 20)
{
let content = template._contentRight().firstElementChild;
let rect = content.getBoundingClientRect();

touchevents.start = true;
touchevents.type = numTouches > 1 || haveZoom || readingViewIs('scroll') ? 'zoom' : 'move';
touchevents.touches = touches;
touchevents.numTouches = numTouches;
touchevents.contentRect = rect;
touchevents.distance = numTouches > 1 ? app.distance(touches[0].pageX, touches[0].pageY, touches[1].pageX, touches[1].pageY) : 0;

touchevents.speed = [{
time: performance.now(),
pageX: app.pageX(event),
}];
}
}

if(touchevents.start)
{
let contentRight = template._contentRight();

if(touchevents.type == 'move')
{
let pageX = app.pageX(event);

let left = (touchevents.contentRect.width * (currentIndex - 1));
left = left - (pageX - app.pageX(touchevents));

if(left < 0)
left = 0;
else if(left > (contentNum - 1) * touchevents.contentRect.width)
left = (contentNum - 1) * touchevents.contentRect.width;

dom.this(contentRight).find('.reading-body > div, .reading-lens > div > div', true).css({
transition: '0s',
transform: 'translate('+(-left)+'px, 0)',
});

if(touchevents.speed.length > 2)
touchevents.speed.shift();

touchevents.speed.push({
time: performance.now(),
pageX: pageX,
});
}
else if(touchevents.type == 'zoom')
{
if(numTouches > 1 && touchevents.numTouches > 1)
{
let distance = app.distance(touches[0].pageX, touches[0].pageY, touches[1].pageX, touches[1].pageY);

let scale = distance / touchevents.distance * currentScale;
touchevents.scale = scale;

let pageX = (touches[0].pageX - touches[1].pageX) + touches[0].pageX;
let pageY = (touches[0].pageY - touches[1].pageY) + touches[0].pageY;

currentPageXY.x = pageX;
currentPageXY.y = pageY;

//x = pageX - ((touchevents.touches[0].pageX - touchevents.touches[1].pageX) + touchevents.touches[0].pageX);
//y = pageY - ((touchevents.touches[0].pageY - touchevents.touches[1].pageY) + touchevents.touches[0].pageY);

//dragZoom(x, y);
applyScale(false, scale);
}
else if(touchevents.numTouches == 1 && haveZoom)
{
let x = app.pageX(event) - app.pageX(touchevents);
let y = app.pageY(event) - app.pageY(touchevents);

dragZoom(x, y);
}
}
}

contentLeftRect = false;
contentRightRect = false;
barHeaderRect = false;
}

if(readingDragScroll) // Drag to scroll
{
event.preventDefault();
Expand Down Expand Up @@ -3278,6 +3387,41 @@ function mousemove(event)
}
}

function mousedown(event)
{
if(haveZoom)
{
if((!config.readingMoveZoomWithMouse || !(event instanceof MouseEvent)) || (readingViewIs('scroll') && !config.readingScrollWithMouse))
{
if(!(event instanceof TouchEvent))
event.preventDefault();

zoomMoveData = {
x: app.pageX(event),
y: app.pageY(event),
active: true,
};

dom.query('body').addClass('dragging');
}
}

if(event instanceof TouchEvent)
{
if(!event.target.closest('.reading-lens'))
{
if(!touchevents.active)
{
touchevents.active = true;
touchevents.start = false;
touchevents.touches = event.touches;
touchevents.touchesXY = app.touchesXY(event);
touchevents.maxTouches = event.touches.length;
}
}
}
}

function mouseenter()
{
isMouseenter.document = true;
Expand Down Expand Up @@ -3690,30 +3834,66 @@ async function read(path, index = 1, end = false, isCanvas = false)

});

template.contentRight('.reading-body, .reading-lens').on('mousedown touchstart', function(e) {
app.event('.reading-body, .reading-lens', 'mousedown touchstart', mousedown);
app.event(window, 'mousemove touchmove', mousemove);

if(haveZoom)
$(window).on('mouseup touchend', function(e) {

if(e.originalEvent instanceof TouchEvent)
{
if(!config.readingMoveZoomWithMouse || (readingViewIs('scroll') && !config.readingScrollWithMouse))
if(e.originalEvent.touches.length == 0)
{
e.preventDefault();

zoomMoveData = {
x: e.originalEvent.touches ? e.originalEvent.touches[0].pageX : (e.pageX ? e.pageX : e.clientX),
y: e.originalEvent.touches ? e.originalEvent.touches[0].pageY : (e.pageY ? e.pageY : e.clientY),
active: true,
};
if(touchevents.active)
{
if(touchevents.start)
{
if(touchevents.type == 'move')
{
let first = touchevents.speed[0];
let last = touchevents.speed[touchevents.speed.length-1];

let dragSpeed = (first.pageX - last.pageX) / ((performance.now() - first.time) / 1000);

if(Math.abs(dragSpeed) > 120)
{
if(dragSpeed > 0)
reading.goNext();
else
reading.goPrev();
}
else
{
let diff = app.pageX(touchevents) - last.pageX;

if(Math.abs(diff) > touchevents.contentRect.width / 2)
{
if(diff > 0)
reading.goNext();
else
reading.goPrev();
}
else
{
goToIndex(currentIndex, true);
}
}
}
else if(touchevents.type == 'zoom')
{
currentScale = touchevents.scale;
}
}
else if(touchevents.maxTouches > 1)
{
reading.resetZoom();
}
}

dom.query('body').addClass('dragging');
touchevents.start = false;
touchevents.active = false;
}
}

});

app.event(window, 'mousemove touchmove', mousemove);

$(window).on('mouseup touchend', function(e) {

if(haveZoom && zoomMoveData.active)
{
dragZoomEnd();
Expand Down Expand Up @@ -3960,6 +4140,7 @@ module.exports = {
zoomIn: zoomIn,
zoomOut: zoomOut,
resetZoom: resetZoom,
dragZoom: dragZoom,
applyScale: applyScale,
activeMagnifyingGlass: activeMagnifyingGlass,
changeMagnifyingGlass: changeMagnifyingGlass,
Expand Down
2 changes: 2 additions & 0 deletions themes/material-design/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,8 @@ body
cursor: default;
overflow: hidden;
transition: color 0.2s;
-webkit-tap-highlight-color: transparent;
-webkit-touch-callout: none;
}

body .app
Expand Down

0 comments on commit f848463

Please sign in to comment.