Page turn gestures in paged mode

This commit is contained in:
Kovid Goyal 2016-08-19 09:27:38 +05:30
parent 7884ffb23e
commit a832c170fc
4 changed files with 67 additions and 4 deletions

View File

@ -99,3 +99,5 @@ def flow_onkeydown(evt):
def layout(is_single_page): def layout(is_single_page):
set_css(document.body, margin='0', border_width='0', padding='0') set_css(document.body, margin='0', border_width='0', padding='0')
def handle_gesture(gesture):
pass

View File

@ -10,12 +10,12 @@ from read_book.globals import set_boss, set_current_spine_item, current_layout_m
from read_book.mathjax import apply_mathjax from read_book.mathjax import apply_mathjax
from read_book.resources import finalize_resources, unserialize_html from read_book.resources import finalize_resources, unserialize_html
from read_book.flow_mode import ( from read_book.flow_mode import (
flow_to_scroll_fraction, flow_onwheel, flow_onkeydown, layout as flow_layout flow_to_scroll_fraction, flow_onwheel, flow_onkeydown, layout as flow_layout, handle_gesture as flow_handle_gesture
) )
from read_book.paged_mode import ( from read_book.paged_mode import (
layout as paged_layout, scroll_to_fraction as paged_scroll_to_fraction, layout as paged_layout, scroll_to_fraction as paged_scroll_to_fraction,
onwheel as paged_onwheel, onkeydown as paged_onkeydown, scroll_to_elem, onwheel as paged_onwheel, onkeydown as paged_onkeydown, scroll_to_elem,
jump_to_cfi as paged_jump_to_cfi jump_to_cfi as paged_jump_to_cfi, handle_gesture as paged_handle_gesture
) )
from read_book.settings import apply_settings from read_book.settings import apply_settings
from read_book.touch import create_handlers as create_touch_handlers from read_book.touch import create_handlers as create_touch_handlers
@ -94,6 +94,7 @@ class IframeBoss:
self.do_layout = flow_layout self.do_layout = flow_layout
self.handle_wheel = flow_onwheel self.handle_wheel = flow_onwheel
self.handle_keydown = flow_onkeydown self.handle_keydown = flow_onkeydown
self.handle_gesture = flow_handle_gesture
self.to_scroll_fraction = flow_to_scroll_fraction self.to_scroll_fraction = flow_to_scroll_fraction
self.jump_to_cfi = scroll_to_cfi self.jump_to_cfi = scroll_to_cfi
else: else:
@ -102,6 +103,7 @@ class IframeBoss:
self.handle_keydown = paged_onkeydown self.handle_keydown = paged_onkeydown
self.to_scroll_fraction = paged_scroll_to_fraction self.to_scroll_fraction = paged_scroll_to_fraction
self.jump_to_cfi = paged_jump_to_cfi self.jump_to_cfi = paged_jump_to_cfi
self.handle_gesture = paged_handle_gesture
apply_settings(data.settings) apply_settings(data.settings)
set_current_spine_item({'name':data.name, 'is_first':index is 0, 'is_last':index is spine.length - 1, 'initial_position':data.initial_position}) set_current_spine_item({'name':data.name, 'is_first':index is 0, 'is_last':index is spine.length - 1, 'initial_position':data.initial_position})
self.last_cfi = None self.last_cfi = None

View File

@ -492,3 +492,11 @@ def onkeydown(evt):
scroll_by_page(key is 'pageup', True) scroll_by_page(key is 'pageup', True)
if handled: if handled:
evt.preventDefault() evt.preventDefault()
def handle_gesture(gesture):
if gesture.type is 'swipe':
if not gesture.active:
if gesture.axis is 'vertical':
pass # TODO: next/prev section
else:
scroll_by_page(gesture.direction is 'right', False)

View File

@ -2,10 +2,44 @@
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import hash_literals, bound_methods from __python__ import hash_literals, bound_methods
from read_book.globals import get_boss
def copy_touch(t): def copy_touch(t):
now = window.performance.now()
return {'identifier':t.identifier, 'page_x':v'[t.pageX]', 'page_y':v'[t.pageY]', 'viewport_x':v'[t.clientX]', 'viewport_y':v'[t.clientY]', return {'identifier':t.identifier, 'page_x':v'[t.pageX]', 'page_y':v'[t.pageY]', 'viewport_x':v'[t.clientX]', 'viewport_y':v'[t.clientY]',
'active':True, 'mtime':window.performance.now()} 'active':True, 'mtime':now, 'ctime':now}
def max_displacement(points):
ans = 0
first = points[0]
if not first?:
return ans
for p in points:
delta = abs(p - first)
if delta > ans:
ans = delta
return ans
def interpret_single_gesture(touch):
max_x_displacement = max_displacement(touch.viewport_x)
max_y_displacement = max_displacement(touch.viewport_y)
if max(max_x_displacement, max_y_displacement) < 25:
return {'type':'tap'}
if touch.viewport_y.length < 2:
return {}
delta_x = abs(touch.viewport_x[-1] - touch.viewport_x[0])
delta_y = abs(touch.viewport_y[-1] - touch.viewport_y[0])
if max(delta_y, delta_x) > 30 and min(delta_x, delta_y)/max(delta_y, delta_x) < 0.35:
ans = {'type':'swipe'}
ans.axis = 'vertical' if delta_y > delta_x else 'horizontal'
pts = touch.viewport_y if ans.axis is 'vertical' else touch.viewport_x
positive = pts[-1] > pts[0]
if ans.axis is 'vertical':
ans.direction = 'down' if positive else 'up'
else:
ans.direction = 'right' if positive else 'left'
return ans
return {}
class TouchHandler: class TouchHandler:
@ -43,6 +77,12 @@ class TouchHandler:
t = self.ongoing_touches[touch.identifier] t = self.ongoing_touches[touch.identifier]
if t: if t:
self.update_touch(t, touch) self.update_touch(t, touch)
if len(self.ongoing_touches) is 1:
gesture = interpret_single_gesture(t)
if gesture?.type is 'swipe':
gesture.active = True
get_boss().handle_gesture(gesture)
def handle_touchend(self, ev): def handle_touchend(self, ev):
ev.preventDefault(), ev.stopPropagation() ev.preventDefault(), ev.stopPropagation()
@ -61,7 +101,18 @@ class TouchHandler:
v'delete self.ongoing_touches[touch.identifier]' v'delete self.ongoing_touches[touch.identifier]'
def interpret_gesture(self, touches): def interpret_gesture(self, touches):
print(1111111, touches) num = len(touches)
gesture = {}
if num is 1:
gesture = interpret_single_gesture(touches[Object.keys(touches)[0]])
if not gesture?.type:
return
if gesture.type is 'tap':
# TODO: Check for tap on link. Also convert the tap gesture into
# semantic gestures based on position of tap (next page/previous
# page/show ui) as these are common to both paged and flow mode.
pass
get_boss().handle_gesture(gesture)
touch_handler = TouchHandler() touch_handler = TouchHandler()