From 025aafc1775d501d3a7b8b57c5bc0968ee9d0b8e Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Tue, 19 Feb 2013 19:34:03 +0400 Subject: [PATCH] fixed setCurrentPage, still a couple of problems with getMagazineOffset + some minor touchups... Signed-off-by: Alex A. Naanou --- layout-iscroll2.html | 109 +----------------------- layout.js | 196 ++++++++++++++++++++++++++++++++++++------- lib/jli.js | 81 ++++++++++++++++-- magazine.js | 72 +--------------- 4 files changed, 246 insertions(+), 212 deletions(-) diff --git a/layout-iscroll2.html b/layout-iscroll2.html index ff6a93f..0c6ad2a 100755 --- a/layout-iscroll2.html +++ b/layout-iscroll2.html @@ -100,6 +100,9 @@ $(document).ready(function(){ 'default': nextPage, // Space 'shift': prevPage // shift-Space }, + // combined navigation with actions.. + 38: function(){togglePageView()}, // Up + 40: function(){togglePageView()}, // Down 70: function(){ // F togglePageFitMode() @@ -137,112 +140,6 @@ $(document).ready(function(){ //limit_scroll() }) -function makeScrollHandler(root, callback){ - - // local data... - var scrolling = false - var touch = false - var touches = 0 - var start - var prev_x - var prev_t - var shift - var scale - var x - var t - var dx - var dt - - function startMoveHandler(evt, callback){ - prev_t = event.timeStamp || Date.now(); - if(event.touches != null){ - touch = true - } - scrolling = true - scroller.state = 'scrolling' - //root.trigger('userScrollStart') - //togglePageDragging('on') - shift = getMagazineShift() - scale = getMagazineScale() - // get the user coords... - prev_x = touch ? event.touches[0].pageX : evt.clientX - start = prev_x - - return false - } - // XXX add limits to this... - // XXX try and make this adaptive to stay ahead of the lags... - function moveHandler(evt){ - evt.preventDefault() - t = event.timeStamp || Date.now(); - // get the user coords... - x = touch ? event.touches[0].pageX : evt.clientX - touches = touch ? event.touches.length : 0 - if(scrolling){ - shift += x - prev_x - shiftMagazineTo(shift, scale) - } - dx = x - prev_x - dt = t - prev_t - prev_t = t - prev_x = x - //root.trigger('userScroll') - } - function endMoveHandler(evt){ - x = touch ? event.changedTouches[0].pageX : evt.clientX - touch = false - scrolling = false - scroller.state = 'waiting' - touches = 0 - //togglePageDragging('off') - // XXX add speed to this... - //root.trigger('userScrollEnd') - callback && callback(dx/dt, start - x) - } - - var scroller = { - start: function(){ - this.state = 'waiting' - // XXX STUB: this makes starting the scroll a bit sluggish, - // find a faster way... - togglePageDragging('on') - - // NOTE: if we bind both touch and mouse events, on touch devices they - // might start interfering with each other... - if('ontouchmove' in window){ - root - .on('touchstart', startMoveHandler) - .on('touchmove', moveHandler) - .on('touchend', endMoveHandler) - } else { - root - .on('mousedown', startMoveHandler) - .on('mousemove', moveHandler) - .on('mouseup', endMoveHandler) - } - return this - }, - stop: function(){ - this.state = 'stopped' - if('ontouchmove' in window){ - root - .off('touchstart', startMoveHandler) - .off('touchmove', moveHandler) - .off('touchend', endMoveHandler) - } else { - root - .off('mousedown', startMoveHandler) - .off('mousemove', moveHandler) - .off('mouseup', endMoveHandler) - } - return this - }, - // NOTE: this is updated live but not used by the system in any way... - state: 'stopped' - } - return scroller -} - var SCROLL_LIMIT = 800 * 1.5 diff --git a/layout.js b/layout.js index dc6a448..909747a 100755 --- a/layout.js +++ b/layout.js @@ -76,8 +76,159 @@ var togglePageView = createCSSClassToggler( +/************************************************** event handlers ***/ + +function makeScrollHandler(root, callback){ + + // local data... + var scrolling = false + var touch = false + var touches = 0 + var start + var prev_x + var prev_t + var shift + var scale + var x + var t + var dx + var dt + + function startMoveHandler(evt, callback){ + prev_t = event.timeStamp || Date.now(); + setTransitionDuration($('.magazine'), 0) + if(event.touches != null){ + touch = true + } + scrolling = true + scroller.state = 'scrolling' + //root.trigger('userScrollStart') + //togglePageDragging('on') + shift = getMagazineShift() + scale = getMagazineScale() + // get the user coords... + prev_x = touch ? event.touches[0].pageX : evt.clientX + start = prev_x + + return false + } + // XXX add limits to this... + // XXX try and make this adaptive to stay ahead of the lags... + function moveHandler(evt){ + evt.preventDefault() + t = event.timeStamp || Date.now(); + // get the user coords... + x = touch ? event.touches[0].pageX : evt.clientX + touches = touch ? event.touches.length : 0 + if(scrolling){ + shift += x - prev_x + setElementTransform($('.magazine'), shift, scale) + } + dx = x - prev_x + dt = t - prev_t + prev_t = t + prev_x = x + //root.trigger('userScroll') + + return false + } + function endMoveHandler(evt){ + // XXX get real transition duration... + setTransitionDuration($('.magazine'), 200) + x = touch ? event.changedTouches[0].pageX : evt.clientX + touch = false + scrolling = false + scroller.state = 'waiting' + touches = 0 + //togglePageDragging('off') + // XXX add speed to this... + //root.trigger('userScrollEnd') + callback && callback(dx/dt, start - x) + + return false + } + + var scroller = { + start: function(){ + this.state = 'waiting' + // XXX STUB: this makes starting the scroll a bit sluggish, + // find a faster way... + //togglePageDragging('on') + + // NOTE: if we bind both touch and mouse events, on touch devices they + // might start interfering with each other... + if('ontouchmove' in window){ + root + .on('touchstart', startMoveHandler) + .on('touchmove', moveHandler) + .on('touchend', endMoveHandler) + } else { + root + .on('mousedown', startMoveHandler) + .on('mousemove', moveHandler) + .on('mouseup', endMoveHandler) + } + return this + }, + stop: function(){ + this.state = 'stopped' + if('ontouchmove' in window){ + root + .off('touchstart', startMoveHandler) + .off('touchmove', moveHandler) + .off('touchend', endMoveHandler) + } else { + root + .off('mousedown', startMoveHandler) + .off('mousemove', moveHandler) + .off('mouseup', endMoveHandler) + } + return this + }, + // NOTE: this is updated live but not used by the system in any way... + state: 'stopped' + } + return scroller +} + + + /********************************************************* helpers ***/ +// XXX there is something here that depends on scale that is either not +// compensated, or is over compensated... +function getMagazineOffset(page, scale, align){ + if(page == null){ + page = $('.current.page') + } + if(scale == null){ + scale = getMagazineScale() + } + if(align == null){ + align = getPageAlign(page) + } + var mag = $('.magazine') + + // calculate the align offset... + if(align == 'left'){ + var offset = 0 + + } else if(align == 'right'){ + var offset = $('.viewer').width() - page.width()*scale + + // center (default) + } else { + var offset = $('.viewer').width()/2 - (page.width()/2)*scale + } + + var w = mag.outerWidth(true) + // XXX this depends on scale... + var pos = page.position().left//*scale + + return -((w - w*scale)/2 + pos) + offset +} + + // XXX make this work for narrow and left/right alligned pages... function getPageNumber(page){ // a page is given... @@ -100,12 +251,10 @@ function getPageNumber(page){ var res = $('.page').map(function(i, e){ e = $(e) var l = e.position().left - //var l = e.offset().left var w = e.width()*scale - //return Math.abs((l+(w/2)) - (s+(W/2))) return Math.abs((l+(w/2)) - (o+(W/2))) - }) - cur = res.index(Math.min.apply(Math, res)) + }).toArray() + cur = res.indexOf(Math.min.apply(Math, res)) return cur } } @@ -116,16 +265,11 @@ function getMagazineScale(){ } function setMagazineScale(scale){ var mag = $('.magazine') - // NOTE: we are updating margins to make the scroll area adapt to new scale... - var w = mag.width() - var m = -(w - (w*scale))/2 + $('.viewer').width()/2 - mag.css({ - 'margin-left': m, - 'margin-right': m - // XXX also add margins at top and bottom for vertical elements... - }) - setElementScale(mag, scale) - //setCurrentPage() + var cur = $('.current.page') + + var left = getMagazineOffset(cur, scale, 'center') + + setElementTransform(mag, left, scale) } @@ -141,26 +285,16 @@ function setCurrentPage(n){ n = n < 0 ? l - n : n n = n < -l ? 0 : n n = n >= l ? l - 1 : n + $('.current.page').removeClass('current') $($('.page')[n]).addClass('current') + var cur = $('.current.page') - if(USE_PAGE_ALIGN - && $('.page').width()*2*scale > $('.viewer').width()){ - var align = getPageAlign() - } else { - var align = 'center' - } - if(align == 'left'){ - var offset = 0 - } else if(align == 'right'){ - var offset = $('.viewer').width() - cur.width()*scale - } else { - var offset = $('.viewer').width()/2 - (cur.width()/2)*scale - } - cur.ScrollTo({ - offsetTop: $('.viewer').height()/2 - (cur.height()/2)*scale, - offsetLeft: offset - }) + + var left = getMagazineOffset(cur) + + setElementTransform($('.magazine'), left, scale) + return cur } diff --git a/lib/jli.js b/lib/jli.js index 33194bf..8d9f19e 100755 --- a/lib/jli.js +++ b/lib/jli.js @@ -194,6 +194,44 @@ function unanimated(obj, func, time){ +// NOTE: at this point this works only on the X axis... +function setElementTransform(elem, offset, scale){ + if(offset == null){ + var offset = getElementShift(elem).left + } + if(scale == null){ + var scale = getElementScale(elem) + } + if(USE_TRANSFORM){ + var transform = 'translate('+ offset +'px, 0px) scale('+ scale +') translateZ(0px)' + elem.css({ + '-ms-transform' : transform, + '-webkit-transform' : transform, + '-moz-transform' : transform, + '-o-transform' : transform, + 'transform' : transform, + + // XXX can we avoid this here?? + left: 0 + }) + } else { + var transform = 'translate(0px, 0px) scale('+ scale +') translateZ(0px)' + elem.css({ + // NOTE: this will be wrong during a transition, that's why we + // can pass the pre-calculated offset as an argument... + left: offset, + + // XXX can we avoid this here?? + '-ms-transform' : transform, + '-webkit-transform' : transform, + '-moz-transform' : transform, + '-o-transform' : transform, + 'transform' : transform, + }) + } + return elem +} + // Return a scale value for the given element(s). // NOTE: this will only return a single scale value... function getElementScale(elem){ @@ -220,14 +258,43 @@ function getElementScale(elem){ return parseFloat((/(scale|matrix)\(([^,]*),.*\)/).exec(transform)[2]) } +// XXX account for other transitions... function setElementScale(elem, scale){ - return elem.css({ - 'transform': 'scale('+scale+')', - '-moz-transform': 'scale('+scale+')', - '-o-transform': 'scale('+scale+')', - '-ms-transform': 'scale('+scale+')', - '-webkit-transform': 'scale('+scale+')', - }) + return setElementTransform(elem, null, scale) +} + +function getElementShift(elem){ + elem = $(elem) + // using transform... + if(USE_TRANSFORM){ + var vendors = ['o', 'moz', 'ms', 'webkit'] + var transform = elem.css('transform') + var res + + // go through vendor prefixes... (hate this!) + if(!transform || transform == 'none'){ + for(var i in vendors){ + transform = elem.css('-' + vendors[i] + '-transform') + if(transform && transform != 'none'){ + break + } + } + } + // no transform is set... + if(!transform || transform == 'none'){ + return {left: 0, top: 0} + } + return { + left: parseFloat(/(translate\(|matrix\([^,]*,[^,]*,[^,]*,[^,]*,)([^,]*),/.exec(transform)[2]), + top: null + } + // using left... + } else { + return { + left: elem.position().left, + top: null + } + } } diff --git a/magazine.js b/magazine.js index a4f12ec..707d001 100755 --- a/magazine.js +++ b/magazine.js @@ -192,7 +192,7 @@ function getPageScale(){ return getElementScale($('.scaler')) } function setPageScale(scale){ - return setElementScale($('.scaler'), scale) + return setElementTransform($('.scaler'), null, scale) } @@ -216,75 +216,11 @@ function getPageAt(n){ return $(page[n]) } -// NOTE: at this point this works only on the X axis... -function shiftMagazineTo(offset, scale){ - var mag = $('.magazine') - if(scale == null){ - var scale = getElementScale(mag) - } - if(USE_TRANSFORM){ - var transform = 'translate('+ offset +'px, 0px) scale('+ scale +') translateZ(0px)' - mag.css({ - '-ms-transform' : transform, - '-webkit-transform' : transform, - '-moz-transform' : transform, - '-o-transform' : transform, - 'transform' : transform, - - // XXX can we avoid this here?? - left: 0, - }) - } else { - var transform = 'translate(0px, 0px) scale('+ scale +') translateZ(0px)' - mag.css({ - // NOTE: this will be wrong during a transition, that's why we - // can pass the pre-calculated offset as an argument... - left: offset, - - // XXX can we avoid this here?? - '-ms-transform' : transform, - '-webkit-transform' : transform, - '-moz-transform' : transform, - '-o-transform' : transform, - 'transform' : transform, - }) - } +function shiftMagazineTo(offset){ + setElementTransform($('.magazine'), offset) } + // XXX this is almost the same as getElementScale... -function getElementShift(elem){ - elem = $(elem) - // using transform... - if(USE_TRANSFORM){ - var vendors = ['o', 'moz', 'ms', 'webkit'] - var transform = elem.css('transform') - var res - - // go through vendor prefixes... (hate this!) - if(!transform || transform == 'none'){ - for(var i in vendors){ - transform = elem.css('-' + vendors[i] + '-transform') - if(transform && transform != 'none'){ - break - } - } - } - // no transform is set... - if(!transform || transform == 'none'){ - return {left: 0, top: 0} - } - return { - left: parseFloat(/(translate\(|matrix\([^,]*,[^,]*,[^,]*,[^,]*,)([^,]*),/.exec(transform)[2]), - top: null - } - // using left... - } else { - return { - left: elem.position().left, - top: null - } - } -} - function getMagazineShift(){ return getElementShift($('.magazine')).left }