Skip to content

Commit f848463

Browse files
committed
New: Improved touch screen navigation (swipe gesture, 2 finger zoom and reset zoom with 2 finger click)
1 parent ff9a96b commit f848463

File tree

4 files changed

+249
-31
lines changed

4 files changed

+249
-31
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
1313
- Option to start OpenComic directly in last reading [`00cb8c7`](https://github.com/ollm/OpenComic/commit/00cb8c7da9eb8345aaec8faa3b5c91953c2350dd)
1414
- Recently opened page [`d2f3065`](https://github.com/ollm/OpenComic/commit/d2f30653f506993a45e49ad5e7e5e8434c33a9be)
1515
- Option to move zoom and scroll whit mouse [`e8cc79c`](https://github.com/ollm/OpenComic/commit/e8cc79cbddd23ff7d47b7046190cecbad199d3c2)
16+
- Improved touch screen navigation (swipe gesture, 2 finger zoom and reset zoom with 2 finger click)
1617

1718
##### 🐛 Bug Fixes
1819

scripts/app.js

+34
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,37 @@ function clientX(e) {
144144

145145
}
146146

147+
function touchesXY(e)
148+
{
149+
let touches = [];
150+
151+
for(let i = 0, len = e.touches.length; i < len; i++)
152+
{
153+
touches.push(e.touches[i].pageX);
154+
touches.push(e.touches[i].pageY);
155+
}
156+
157+
return touches;
158+
}
159+
160+
function touchesDiff(touches0, touches1)
161+
{
162+
let touches = [];
163+
164+
for(let i = 0, len = touches0.length; i < len; i++)
165+
{
166+
if(touches1[i] !== undefined)
167+
touches.push(Math.abs(touches0[i] - touches1[i]));
168+
}
169+
170+
return touches;
171+
}
172+
173+
function distance(x1, y1, x2, y2)
174+
{
175+
return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2);
176+
}
177+
147178
function rand(min = 0, max = 10000000)
148179
{
149180
return Math.floor(Math.random() * (max - min + 1)) + min;
@@ -176,6 +207,9 @@ module.exports = {
176207
pageX: pageX,
177208
clientY: clientY,
178209
clientX: clientX,
210+
touchesXY: touchesXY,
211+
touchesDiff: touchesDiff,
212+
distance: distance,
179213
rand: rand,
180214
sleep: sleep,
181215
setImmediate: setImmediate,

scripts/reading.js

+212-31
Original file line numberDiff line numberDiff line change
@@ -1453,11 +1453,6 @@ function showPreviousComic(mode, animation = true, invert = false)
14531453

14541454
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;
14551455

1456-
function applyScaleScrollAndHeight()
1457-
{
1458-
1459-
}
1460-
14611456
function applyScale(animation = true, scale = 1, center = false, zoomOut = false, round = true)
14621457
{
14631458
let animationDurationS = ((animation) ? _config.readingViewSpeed : 0);
@@ -3153,7 +3148,7 @@ function eachImagesDistribution(index, contains, callback, first = false, notFou
31533148

31543149
// Events functions
31553150

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

31583153
function mousemove(event)
31593154
{
@@ -3167,20 +3162,32 @@ function mousemove(event)
31673162

31683163
if(haveZoom) // Drag Image zoom
31693164
{
3170-
if(config.readingMoveZoomWithMouse && (!readingViewIs('scroll') || config.readingScrollWithMouse) && !(event instanceof PointerEvent))
3165+
if(contentRightRect === false)
31713166
{
3172-
event.preventDefault();
3167+
contentRightRect = template._contentRight().getBoundingClientRect();
3168+
let _contentRightRect = template._contentRight().firstElementChild.firstElementChild.getBoundingClientRect();
3169+
contentRightRect.width = _contentRightRect.width;
3170+
}
31733171

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

3177-
dragZoom(x, y);
3178+
let _pageX = pageX - contentRightRect.left;
3179+
let _pageY = pageY - contentRightRect.top;
31783180

3179-
scalePrevData.tranX = zoomMoveData.tranX;
3180-
scalePrevData.tranY = zoomMoveData.tranY;
3181+
let x = -(_pageX - contentRightRect.width / 2) * (scalePrevData.scale - 1);
3182+
let y = -(_pageY - contentRightRect.height / 2) * (scalePrevData.scale - 1);
31813183

3184+
dragZoom(x - scalePrevData.tranX2, y - scalePrevData.tranY2);
3185+
3186+
scalePrevData.tranX = zoomMoveData.tranX;
3187+
scalePrevData.tranY = zoomMoveData.tranY;
3188+
}
31823189
}
3183-
else if(zoomMoveData.active)
3190+
else if(zoomMoveData.active && !(event instanceof TouchEvent))
31843191
{
31853192
event.preventDefault();
31863193

@@ -3191,6 +3198,108 @@ function mousemove(event)
31913198
}
31923199
}
31933200

3201+
if(touchevents.active && event instanceof TouchEvent)
3202+
{
3203+
let touches = event.touches;
3204+
3205+
// Simulate touch with 2 fingers
3206+
if(event.ctrlKey)
3207+
touches = [event.touches[0], touchevents.touches[1] || touchevents.touches[0]];
3208+
3209+
let numTouches = touches.length;
3210+
3211+
if(numTouches > touchevents.maxTouches)
3212+
touchevents.maxTouches = numTouches;
3213+
3214+
if(!touchevents.start)
3215+
{
3216+
let touchesXY = app.touchesXY(event);
3217+
let maxDiff = Math.max(...app.touchesDiff(touchevents.touchesXY, touchesXY));
3218+
3219+
if(maxDiff > 20)
3220+
{
3221+
let content = template._contentRight().firstElementChild;
3222+
let rect = content.getBoundingClientRect();
3223+
3224+
touchevents.start = true;
3225+
touchevents.type = numTouches > 1 || haveZoom || readingViewIs('scroll') ? 'zoom' : 'move';
3226+
touchevents.touches = touches;
3227+
touchevents.numTouches = numTouches;
3228+
touchevents.contentRect = rect;
3229+
touchevents.distance = numTouches > 1 ? app.distance(touches[0].pageX, touches[0].pageY, touches[1].pageX, touches[1].pageY) : 0;
3230+
3231+
touchevents.speed = [{
3232+
time: performance.now(),
3233+
pageX: app.pageX(event),
3234+
}];
3235+
}
3236+
}
3237+
3238+
if(touchevents.start)
3239+
{
3240+
let contentRight = template._contentRight();
3241+
3242+
if(touchevents.type == 'move')
3243+
{
3244+
let pageX = app.pageX(event);
3245+
3246+
let left = (touchevents.contentRect.width * (currentIndex - 1));
3247+
left = left - (pageX - app.pageX(touchevents));
3248+
3249+
if(left < 0)
3250+
left = 0;
3251+
else if(left > (contentNum - 1) * touchevents.contentRect.width)
3252+
left = (contentNum - 1) * touchevents.contentRect.width;
3253+
3254+
dom.this(contentRight).find('.reading-body > div, .reading-lens > div > div', true).css({
3255+
transition: '0s',
3256+
transform: 'translate('+(-left)+'px, 0)',
3257+
});
3258+
3259+
if(touchevents.speed.length > 2)
3260+
touchevents.speed.shift();
3261+
3262+
touchevents.speed.push({
3263+
time: performance.now(),
3264+
pageX: pageX,
3265+
});
3266+
}
3267+
else if(touchevents.type == 'zoom')
3268+
{
3269+
if(numTouches > 1 && touchevents.numTouches > 1)
3270+
{
3271+
let distance = app.distance(touches[0].pageX, touches[0].pageY, touches[1].pageX, touches[1].pageY);
3272+
3273+
let scale = distance / touchevents.distance * currentScale;
3274+
touchevents.scale = scale;
3275+
3276+
let pageX = (touches[0].pageX - touches[1].pageX) + touches[0].pageX;
3277+
let pageY = (touches[0].pageY - touches[1].pageY) + touches[0].pageY;
3278+
3279+
currentPageXY.x = pageX;
3280+
currentPageXY.y = pageY;
3281+
3282+
//x = pageX - ((touchevents.touches[0].pageX - touchevents.touches[1].pageX) + touchevents.touches[0].pageX);
3283+
//y = pageY - ((touchevents.touches[0].pageY - touchevents.touches[1].pageY) + touchevents.touches[0].pageY);
3284+
3285+
//dragZoom(x, y);
3286+
applyScale(false, scale);
3287+
}
3288+
else if(touchevents.numTouches == 1 && haveZoom)
3289+
{
3290+
let x = app.pageX(event) - app.pageX(touchevents);
3291+
let y = app.pageY(event) - app.pageY(touchevents);
3292+
3293+
dragZoom(x, y);
3294+
}
3295+
}
3296+
}
3297+
3298+
contentLeftRect = false;
3299+
contentRightRect = false;
3300+
barHeaderRect = false;
3301+
}
3302+
31943303
if(readingDragScroll) // Drag to scroll
31953304
{
31963305
event.preventDefault();
@@ -3278,6 +3387,41 @@ function mousemove(event)
32783387
}
32793388
}
32803389

3390+
function mousedown(event)
3391+
{
3392+
if(haveZoom)
3393+
{
3394+
if((!config.readingMoveZoomWithMouse || !(event instanceof MouseEvent)) || (readingViewIs('scroll') && !config.readingScrollWithMouse))
3395+
{
3396+
if(!(event instanceof TouchEvent))
3397+
event.preventDefault();
3398+
3399+
zoomMoveData = {
3400+
x: app.pageX(event),
3401+
y: app.pageY(event),
3402+
active: true,
3403+
};
3404+
3405+
dom.query('body').addClass('dragging');
3406+
}
3407+
}
3408+
3409+
if(event instanceof TouchEvent)
3410+
{
3411+
if(!event.target.closest('.reading-lens'))
3412+
{
3413+
if(!touchevents.active)
3414+
{
3415+
touchevents.active = true;
3416+
touchevents.start = false;
3417+
touchevents.touches = event.touches;
3418+
touchevents.touchesXY = app.touchesXY(event);
3419+
touchevents.maxTouches = event.touches.length;
3420+
}
3421+
}
3422+
}
3423+
}
3424+
32813425
function mouseenter()
32823426
{
32833427
isMouseenter.document = true;
@@ -3690,30 +3834,66 @@ async function read(path, index = 1, end = false, isCanvas = false)
36903834

36913835
});
36923836

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

3695-
if(haveZoom)
3840+
$(window).on('mouseup touchend', function(e) {
3841+
3842+
if(e.originalEvent instanceof TouchEvent)
36963843
{
3697-
if(!config.readingMoveZoomWithMouse || (readingViewIs('scroll') && !config.readingScrollWithMouse))
3844+
if(e.originalEvent.touches.length == 0)
36983845
{
3699-
e.preventDefault();
3700-
3701-
zoomMoveData = {
3702-
x: e.originalEvent.touches ? e.originalEvent.touches[0].pageX : (e.pageX ? e.pageX : e.clientX),
3703-
y: e.originalEvent.touches ? e.originalEvent.touches[0].pageY : (e.pageY ? e.pageY : e.clientY),
3704-
active: true,
3705-
};
3846+
if(touchevents.active)
3847+
{
3848+
if(touchevents.start)
3849+
{
3850+
if(touchevents.type == 'move')
3851+
{
3852+
let first = touchevents.speed[0];
3853+
let last = touchevents.speed[touchevents.speed.length-1];
3854+
3855+
let dragSpeed = (first.pageX - last.pageX) / ((performance.now() - first.time) / 1000);
3856+
3857+
if(Math.abs(dragSpeed) > 120)
3858+
{
3859+
if(dragSpeed > 0)
3860+
reading.goNext();
3861+
else
3862+
reading.goPrev();
3863+
}
3864+
else
3865+
{
3866+
let diff = app.pageX(touchevents) - last.pageX;
3867+
3868+
if(Math.abs(diff) > touchevents.contentRect.width / 2)
3869+
{
3870+
if(diff > 0)
3871+
reading.goNext();
3872+
else
3873+
reading.goPrev();
3874+
}
3875+
else
3876+
{
3877+
goToIndex(currentIndex, true);
3878+
}
3879+
}
3880+
}
3881+
else if(touchevents.type == 'zoom')
3882+
{
3883+
currentScale = touchevents.scale;
3884+
}
3885+
}
3886+
else if(touchevents.maxTouches > 1)
3887+
{
3888+
reading.resetZoom();
3889+
}
3890+
}
37063891

3707-
dom.query('body').addClass('dragging');
3892+
touchevents.start = false;
3893+
touchevents.active = false;
37083894
}
37093895
}
37103896

3711-
});
3712-
3713-
app.event(window, 'mousemove touchmove', mousemove);
3714-
3715-
$(window).on('mouseup touchend', function(e) {
3716-
37173897
if(haveZoom && zoomMoveData.active)
37183898
{
37193899
dragZoomEnd();
@@ -3960,6 +4140,7 @@ module.exports = {
39604140
zoomIn: zoomIn,
39614141
zoomOut: zoomOut,
39624142
resetZoom: resetZoom,
4143+
dragZoom: dragZoom,
39634144
applyScale: applyScale,
39644145
activeMagnifyingGlass: activeMagnifyingGlass,
39654146
changeMagnifyingGlass: changeMagnifyingGlass,

themes/material-design/theme.css

+2
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,8 @@ body
632632
cursor: default;
633633
overflow: hidden;
634634
transition: color 0.2s;
635+
-webkit-tap-highlight-color: transparent;
636+
-webkit-touch-callout: none;
635637
}
636638

637639
body .app

0 commit comments

Comments
 (0)