diff options
author | Andy Huang <ath@google.com> | 2012-11-28 22:38:02 -0800 |
---|---|---|
committer | Andy Huang <ath@google.com> | 2012-12-12 16:55:14 -0800 |
commit | 02f9d18a54072db8d86c524f9c09e508092ddd7c (patch) | |
tree | 712e1b78fefd0e2d9afcc38b791315591fba78ae /assets | |
parent | 0886b2910872b17f6cb6716ee4e92fba3c69d873 (diff) | |
download | android_packages_apps_UnifiedEmail-02f9d18a54072db8d86c524f9c09e508092ddd7c.tar.gz android_packages_apps_UnifiedEmail-02f9d18a54072db8d86c524f9c09e508092ddd7c.tar.bz2 android_packages_apps_UnifiedEmail-02f9d18a54072db8d86c524f9c09e508092ddd7c.zip |
per-message zoom using JavaScript + CSS 3D transforms
When Auto-fit is off, disable built-in WebView zooming, which
is only capable of zooming an entire document (the entire
conversation).
Use ScaleGestureDetector to trigger a CSS 3D transform to zoom
in/out just a single message div.
During the gesture, the elements above and below the message
being scaled are untouched. This is ugly.
TODO: they should either move away (tricky) or at least fade
out.
When the gesture is complete, to avoid leaving overlapping
elements, we force-scale the height and reset the transform
origin to the top left.
TODO: auto-scroll to the correct place to counteract this
perceived jump.
Double-tap is not yet implemented. We'll have to do it
ourselves.
Bug: 7478834
Change-Id: I114e4977304c7060d499d116cc75bc0488967448
Diffstat (limited to 'assets')
-rw-r--r-- | assets/script.js | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/assets/script.js b/assets/script.js index 4a015786f..6ea24e819 100644 --- a/assets/script.js +++ b/assets/script.js @@ -21,6 +21,8 @@ var BLOCKED_SRC_ATTR = "blocked-src"; // this is an Array, but we treat it like a Set and only insert unique items var gImageLoadElements = []; +var gScaleInfo; + /** * Returns the page offset of an element. * @@ -59,6 +61,17 @@ function up(el, className) { return parent || null; } +function getCachedValue(div, property, attrName) { + var value; + if (div.hasAttribute(attrName)) { + value = div.getAttribute(attrName); + } else { + value = div[property]; + div.setAttribute(attrName, value); + } + return value; +} + function onToggleClick(e) { toggleQuotedText(e.target); measurePositions(); @@ -448,6 +461,113 @@ function appendMessageHtml() { measurePositions(); } +function onScaleBegin(screenX, screenY) { +// console.log("JS got scaleBegin x/y=" + screenX + "/" + screenY); + var focusX = screenX + document.body.scrollLeft; + var focusY = screenY + document.body.scrollTop; + var i, len; + var msgDivs = document.getElementsByClassName("mail-message"); + var msgDiv, msgBodyDiv; + var msgTop, msgDivTop, nextMsgTop; + var initialH; + var initialScale; + var scaledOriginX, scaledOriginY; + var translateX, translateY; + var origin; + + gScaleInfo = undefined; + + for (i = 0, len = msgDivs.length; i < len; i++) { + msgDiv = msgDivs[i]; + msgTop = nextMsgTop ? nextMsgTop : getTotalOffset(msgDiv).top; + nextMsgTop = (i < len-1) ? getTotalOffset(msgDivs[i+1]).top : document.body.offsetHeight; + if (focusY >= msgTop && focusY < nextMsgTop) { + msgBodyDiv = msgDiv.children[1]; + initialScale = msgBodyDiv.getAttribute("data-initial-scale") || 1.0; + + msgDivTop = getTotalOffset(msgBodyDiv).top; + + scaledOriginX = focusX;// / initialScale; + scaledOriginY = (focusY - msgDivTop);// / initialScale; + + translateX = scaledOriginX * (initialScale - 1.0) / initialScale; + translateY = scaledOriginY * (initialScale - 1.0) / initialScale; + + gScaleInfo = { + div: msgBodyDiv, + divTop: msgDivTop, + initialScale: initialScale, + initialX: focusX, + initialY: focusY, + translateX: translateX, + translateY: translateY, + initialH: getCachedValue(msgBodyDiv, "offsetHeight", "data-initial-height"), + minScale: Math.min(document.body.offsetWidth / msgBodyDiv.scrollWidth, 1.0), + currScale: initialScale + }; + + origin = scaledOriginX + "px " + scaledOriginY + "px"; + msgBodyDiv.classList.add("zooming-focused"); + msgBodyDiv.style.webkitTransformOrigin = origin; + msgBodyDiv.style.webkitTransform = "scale3d(" + initialScale + "," + initialScale + + ",1) translate3d(" + translateX + "px," + translateY + "px,0)"; +// console.log("scaleBegin, h=" + gScaleInfo.initialH + " origin='" + origin + "'"); + break; + } + } +} + +function onScaleEnd(screenX, screenY) { + var msgBodyDiv; + var scale; + var h; + if (!gScaleInfo) { + return; + } + +// console.log("JS got scaleEnd x/y=" + screenX + "/" + screenY); + msgBodyDiv = gScaleInfo.div; + scale = gScaleInfo.currScale; + msgBodyDiv.style.webkitTransformOrigin = "0 0"; + // clear any translate + msgBodyDiv.style.webkitTransform = "scale3d(" + scale + "," + scale + ",1)"; + // switching to a 2D transform here re-renders the fonts more clearly, but introduces + // texture upload lag to any subsequent scale operation + //msgBodyDiv.style.webkitTransform = "scale(" + gScaleInfo.currScale + ")"; + h = gScaleInfo.initialH * scale; +// console.log("onScaleEnd set h=" + h); + msgBodyDiv.style.height = h + "px"; + msgBodyDiv.classList.remove("zooming-focused"); + msgBodyDiv.setAttribute("data-initial-scale", scale); +} + +function onScale(relativeScale, screenX, screenY) { + var focusX, focusY; + var scale; + var translateX, translateY; + var transform; + + if (!gScaleInfo) { + return; + } + focusX = screenX + document.body.scrollLeft; + focusY = screenY + document.body.scrollTop; + + scale = Math.max(gScaleInfo.initialScale * relativeScale, gScaleInfo.minScale); + if (scale > 4.0) { + scale = 4.0; + } + gScaleInfo.currScale = scale; + translateX = focusX - gScaleInfo.initialX; + translateY = focusY - gScaleInfo.initialY; + transform = "translate3d(" + translateX + "px," + translateY + "px,0) scale3d(" + + scale + "," + scale + ",1) translate3d(" + gScaleInfo.translateX + "px," + + gScaleInfo.translateY + "px,0)"; + gScaleInfo.div.style.webkitTransform = transform; +// console.log("JS got scale=" + relativeScale + " x/y=" + screenX + "/" + screenY +// + " transform='" + transform + "'"); +} + // END Java->JavaScript handlers // Do this first to ensure that the readiness signal comes through, |