/*\ title: js/macros/zoomer.js \*/ (function(){ /*jslint node: true, browser: true */ "use strict"; var Renderer = require("../Renderer.js").Renderer, Dependencies = require("../Dependencies.js").Dependencies, Tiddler = require("../Tiddler.js").Tiddler, utils = require("../Utils.js"); function startZoomer(macroNode,x,y) { macroNode.inZoomer = true; macroNode.startX = x; macroNode.startY = y; utils.addClass(document.body,"in-zoomer"); } function stopZoomer(macroNode) { var newScrollY = macroNode.yFactor * (macroNode.bodyHeight - macroNode.windowHeight); macroNode.inZoomer = false; window.scrollTo(0,newScrollY); document.body.style.webkitTransform = "translateY(" + newScrollY * macroNode.xFactor + "px) " + "scale(" + macroNode.scale + ") " + "translateY(" + ((macroNode.windowHeight / macroNode.scale) - macroNode.bodyHeight) * macroNode.yFactor * macroNode.xFactor + "px)"; utils.removeClass(document.body,"in-zoomer"); document.body.style.webkitTransform = "translateY(0) scale(1) translateY(0)"; } /* Zoom the body element given a touch/mouse position in screen coordinates */ function hoverZoomer(macroNode,x,y) { // Put the transform origin at the top in the middle document.body.style.webkitTransformOrigin = "50% 0"; // Some shortcuts macroNode.bodyWidth = document.body.offsetWidth; macroNode.bodyHeight = document.body.offsetHeight; macroNode.windowWidth = window.innerWidth; macroNode.windowHeight = window.innerHeight; // Compute the scale factor for fitting the entire page into the window. This is // the scale factor we'll use when the touch is far to the left macroNode.minScale = macroNode.windowHeight / macroNode.bodyHeight; if(macroNode.minScale < 0.1) { // Don't scale to less than 10% of original size macroNode.minScale = 0.1; } else if(macroNode.minScale > 1) { // Nor should we scale up if the body is shorter than the window macroNode.minScale = 1; } // We divide the screen into two horizontal zones divided by the right edge of the body at maximum zoom (ie minimum scale) macroNode.splitPos = macroNode.windowWidth/2 + (macroNode.bodyWidth * macroNode.minScale)/2; // Compute the 0->1 ratio (from right to left) of the position of the touch within the right zone macroNode.xFactor = (macroNode.windowWidth - x) / (macroNode.windowWidth - macroNode.splitPos); if(macroNode.xFactor > 1) { macroNode.xFactor = 1; } // And the 0->1 ratio (from top to bottom) of the position of the touch down the screen macroNode.yFactor = y/macroNode.windowHeight; // Now interpolate the scale macroNode.scale = (macroNode.minScale - 1) * macroNode.xFactor + 1; // Apply the transform. The malarkey with .toFixed() is because otherwise we might get numbers in // exponential notation (such as 5.1e-15) that are illegal in CSS var preTranslateY = window.scrollY * macroNode.xFactor, scale = macroNode.scale, postTranslateY = ((macroNode.windowHeight / macroNode.scale) - macroNode.bodyHeight) * macroNode.yFactor * macroNode.xFactor; var transform = "translateY(" + preTranslateY.toFixed(8) + "px) " + "scale(" + scale.toFixed(8) + ") " + "translateY(" + postTranslateY.toFixed(8) + "px)"; document.body.style.webkitTransform = transform; } exports.macro = { name: "zoomer", wrapperTag: "div", params: { }, events: { touchstart: function(event) { startZoomer(this,event.touches[0].clientX,event.touches[0].clientY); hoverZoomer(this,event.touches[0].clientX,event.touches[0].clientY); event.preventDefault(); return false; }, touchmove: function(event) { hoverZoomer(this,event.touches[0].clientX,event.touches[0].clientY); event.preventDefault(); return false; }, touchend: function(event) { stopZoomer(this); event.preventDefault(); return false; } }, execute: function() { this.inZoomer = false; return []; } }; })();