module.exports = function ScalingServiceFactory() { var scalingService = { } scalingService.coordinator = function (realWidth, realHeight) { var realRatio = realWidth / realHeight /** * Rotation affects the screen as follows: * * 0deg * |------| * | MENU | * |------| * --> | | --| * | | | v * | | * | | * |------| * |----|-| |-|----| * | |M| | | | * | |E| | | | * 90deg | |N| |U| | 270deg * | |U| |N| | * | | | |E| | * | | | |M| | * |----|-| |-|----| * |------| * ^ | | | * |-- | | <-- * | | * | | * |------| * | UNEM | * |------| * 180deg * * Which leads to the following mapping: * * |--------------|------|---------|---------|---------| * | | 0deg | 90deg | 180deg | 270deg | * |--------------|------|---------|---------|---------| * | CSS rotate() | 0deg | -90deg | -180deg | 90deg | * | bounding w | w | h | w | h | * | bounding h | h | w | h | w | * | pos x | x | h-y | w-x | y | * | pos y | y | x | h-y | h-x | * |--------------|------|---------|---------|---------| */ return { coords: function (boundingW, boundingH, relX, relY, rotation) { var w, h, x, y, ratio, scaledValue switch (rotation) { case 0: w = boundingW h = boundingH x = relX y = relY break case 90: w = boundingH h = boundingW x = boundingH - relY y = relX break case 180: w = boundingW h = boundingH x = boundingW - relX y = boundingH - relY break case 270: w = boundingH h = boundingW x = relY y = boundingW - relX break } ratio = w / h if (realRatio > ratio) { // covers the area horizontally scaledValue = w / realRatio // adjust y to start from the scaled top edge y -= (h - scaledValue) / 2 // not touching the screen, but we want to trigger certain events // (like touchup) anyway, so let's do it on the edges. if (y < 0) { y = 0 } else if (y > scaledValue) { y = scaledValue } // make sure x is within bounds too if (x < 0) { x = 0 } else if (x > w) { x = w } h = scaledValue } else { // covers the area vertically scaledValue = h * realRatio // adjust x to start from the scaled left edge x -= (w - scaledValue) / 2 // not touching the screen, but we want to trigger certain events // (like touchup) anyway, so let's do it on the edges. if (x < 0) { x = 0 } else if (x > scaledValue) { x = scaledValue } // make sure y is within bounds too if (y < 0) { y = 0 } else if (y > h) { y = h } w = scaledValue } return { xP: x / w , yP: y / h } } , size: function (width, height) { var ratio = width / height if (realRatio > ratio) { // covers the area horizontally if (width >= realWidth) { // don't go over max size width = realWidth height = realHeight } else { height = Math.floor(width / realRatio) } } else { // covers the area vertically if (height >= realHeight) { // don't go over max size height = realHeight width = realWidth } else { width = Math.floor(height * realRatio) } } return { width: width , height: height } } , projectedSize: function (boundingW, boundingH, rotation) { var w, h switch (rotation) { case 0: case 180: w = boundingW h = boundingH break case 90: case 270: w = boundingH h = boundingW break } var ratio = w / h if (realRatio > ratio) { // covers the area horizontally h = Math.floor(w / realRatio) } else { w = Math.floor(h * realRatio) } return { width: w , height: h } } } } return scalingService }