From 685882d19fe1415912d4cea8a9dd69b05ecaecfc Mon Sep 17 00:00:00 2001 From: Simo Kinnunen Date: Wed, 22 Apr 2015 19:31:19 +0900 Subject: [PATCH] The screen should now stretch to fill all the available area while maintaining aspect ratio. Includes a terrifying hack for the 270deg rotation. --- .../components/stf/screen/screen-directive.js | 47 ++++++++-- res/app/components/stf/screen/screen.jade | 5 +- .../device-control/device-control.css | 91 +++++++++++++++++-- 3 files changed, 125 insertions(+), 18 deletions(-) diff --git a/res/app/components/stf/screen/screen-directive.js b/res/app/components/stf/screen/screen-directive.js index 27ced071..358b07ae 100644 --- a/res/app/components/stf/screen/screen-directive.js +++ b/res/app/components/stf/screen/screen-directive.js @@ -215,6 +215,10 @@ module.exports = function DeviceScreenDirective( cachedScreen.rotation !== screen.rotation } + function isRotated() { + return screen.rotation === 90 || screen.rotation === 270 + } + function updateImageArea(img) { if (!hasImageAreaChanged(img)) { return @@ -233,21 +237,26 @@ module.exports = function DeviceScreenDirective( canvas.height = cachedImageHeight } - var projectedSize = scaler.projectedSize( - screen.bounds.w - , screen.bounds.h - , screen.rotation - ) - cssRotation += rotator(cachedScreen.rotation, screen.rotation) - canvas.style.width = projectedSize.width + 'px' - canvas.style.height = projectedSize.height + 'px' canvas.style[cssTransform] = 'rotate(' + cssRotation + 'deg)' cachedScreen.bounds.h = screen.bounds.h cachedScreen.bounds.w = screen.bounds.w cachedScreen.rotation = screen.rotation + + canvasAspect = canvas.width / canvas.height + + if (isRotated()) { + canvasAspect = img.height / img.width + element[0].classList.add('rotated') + } + else { + canvasAspect = img.width / img.height + element[0].classList.remove('rotated') + } + + maybeFlipLetterbox() } return function messageListener(message) { @@ -270,7 +279,7 @@ module.exports = function DeviceScreenDirective( img.onload = function() { updateImageArea(this) - g.drawImage(img, 0, 0) + g.drawImage(img, 0, 0, img.width, img.height) // Try to forcefully clean everything to get rid of memory // leaks. Note that despite this effort, Chrome will still @@ -318,7 +327,7 @@ module.exports = function DeviceScreenDirective( })() // NOTE: instead of fa-pane-resize, a fa-child-pane-resize could be better - cleanupList.push(scope.$on('fa-pane-resize', _.throttle(updateBounds, 1000))) + cleanupList.push(scope.$on('fa-pane-resize', _.debounce(updateBounds, 1000))) cleanupList.push(scope.$watch('device.using', checkEnabled)) cleanupList.push(scope.$on('visibilitychange', checkEnabled)) cleanupList.push(scope.$watch('$parent.showScreen', checkEnabled)) @@ -338,11 +347,29 @@ module.exports = function DeviceScreenDirective( control.rotate(90) }) + var canvasAspect = 1 + , parentAspect = 1 + + function resizeListener() { + parentAspect = element[0].offsetWidth / element[0].offsetHeight + maybeFlipLetterbox() + } + + function maybeFlipLetterbox() { + element[0].classList.toggle( + 'letterboxed', parentAspect < canvasAspect) + } + $window.addEventListener('beforeunload', stop, false) + $window.addEventListener('resize', resizeListener, false) + scope.$on('fa-pane-resize', resizeListener) + + resizeListener() scope.$on('$destroy', function() { stop() $window.removeEventListener('beforeunload', stop, false) + $window.removeEventListener('resize', resizeListener, false) }) })() diff --git a/res/app/components/stf/screen/screen.jade b/res/app/components/stf/screen/screen.jade index 042dceed..8de1f94e 100644 --- a/res/app/components/stf/screen/screen.jade +++ b/res/app/components/stf/screen/screen.jade @@ -1,5 +1,6 @@ -div.screen-center - canvas(ng-show='device') +div.positioner + canvas.screen(ng-show='device') + canvas.hacky-stretcher(width=1, height=1) div(ng-if='displayError').screen-error .screen-error-message nothing-to-show(message='{{"No device screen"|translate}}', icon='fa-eye-slash', ng-show='true') diff --git a/res/app/control-panes/device-control/device-control.css b/res/app/control-panes/device-control/device-control.css index f9cbaa7b..82b7a23f 100644 --- a/res/app/control-panes/device-control/device-control.css +++ b/res/app/control-panes/device-control/device-control.css @@ -18,6 +18,7 @@ device-screen { display: block; overflow: hidden; /*cursor: pointer;*/ + text-align: center; /* needed for centering after rotating to 270 */ -webkit-touch-callout: none; -webkit-user-select: none; @@ -27,17 +28,20 @@ device-screen { user-select: none; } -device-screen .screen-center { +device-screen .positioner { position: absolute; - top: -100%; - right: -100%; - bottom: -100%; - left: -100%; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; pointer-events: none; } -device-screen canvas { +device-screen canvas.screen { position: absolute; + width: 100%; + height: auto; top: 0; right: 0; bottom: 0; @@ -52,6 +56,81 @@ device-screen canvas { transform: rotate(0deg); } +device-screen .positioner .hacky-stretcher { + outline: 1px solid red; + height: 100%; + width: auto; + margin: 0; + padding: 0; + pointer-events: none; +} + +/* screen is in default rotation or upside down, possibly with empty space on left/right */ + +device-screen/*.portrait*/ .positioner { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +device-screen/*.portrait*/ canvas.screen { + width: auto; + height: 100%; +} + +/* screen is in default rotation or upside down, possibly with empty space on top/bottom */ + +device-screen/*.portrait*/.letterboxed .positioner { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +device-screen/*.portrait*/.letterboxed canvas.screen { + width: 100%; + height: auto; +} + +/* screen is rotated sideways, possibly with empty space on left/right */ + +device-screen.rotated .positioner { + position: relative; + display: inline-block; + top: 0; + right: 0; + bottom: 0; + left: 0; + height: 100%; +} + +device-screen.rotated canvas.screen { + width: 100%; + height: auto; +} + +/* screen is rotated sideways, possibly with empty space on top/bottom */ + +device-screen.rotated.letterboxed .positioner { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + margin: auto; + width: 100%; + padding-top: 100%; + height: 0; +} + +device-screen.rotated.letterboxed canvas.screen { + height: 100%; + width: auto; +} + device-screen .finger { position: absolute; border-radius: 50%;