Bug 1132882 - Slave the local video size to the remote video width on the Loop standalone UI. r=mikedeboer

This commit is contained in:
Mark Banner 2015-02-14 09:48:11 +00:00
Родитель 96be378b31
Коммит 004c306bd1
3 изменённых файлов: 166 добавлений и 16 удалений

Просмотреть файл

@ -295,30 +295,54 @@ loop.standaloneRoomViews = (function(mozL10n) {
* @param {Object} ratio Aspect ratio of the local camera stream
*/
updateLocalCameraPosition: function(ratio) {
// The local stream is a quarter of the remote stream.
var LOCAL_STREAM_SIZE = 0.25;
// The local stream overlaps the remote stream by a quarter of the local stream.
var LOCAL_STREAM_OVERLAP = 0.25;
// The minimum size of video height/width allowed by the sdk css.
var SDK_MIN_SIZE = 48;
var node = this._getElement(".local");
var parent = node.offsetParent || this._getElement(".media");
// The local camera view should be a sixth of the size of its offset parent
// and positioned to overlap with the remote stream at a quarter of its width.
var parentWidth = parent.offsetWidth;
var targetWidth = parentWidth / 6;
var targetWidth;
node.style.right = "auto";
if (window.matchMedia && window.matchMedia("screen and (max-width:640px)").matches) {
// For reduced screen widths, we just go for a fixed size and no overlap.
targetWidth = 180;
node.style.width = (targetWidth * ratio.width) + "px";
node.style.height = (targetWidth * ratio.height) + "px";
node.style.left = "auto";
} else {
// The local camera view should be a quarter of the size of the remote stream
// and positioned to overlap with the remote stream at a quarter of its width.
// Now position the local camera view correctly with respect to the remote
// video stream.
var remoteVideoDimensions = this.getRemoteVideoDimensions();
targetWidth = remoteVideoDimensions.streamWidth * LOCAL_STREAM_SIZE;
var realWidth = targetWidth * ratio.width;
var realHeight = targetWidth * ratio.height;
// If we've hit the min size limits, then limit at the minimum.
if (realWidth < SDK_MIN_SIZE) {
realWidth = SDK_MIN_SIZE;
realHeight = realWidth / ratio.width * ratio.height;
}
if (realHeight < SDK_MIN_SIZE) {
realHeight = SDK_MIN_SIZE;
realWidth = realHeight / ratio.height * ratio.width;
}
var offsetX = (remoteVideoDimensions.streamWidth + remoteVideoDimensions.offsetX);
// The horizontal offset of the stream, and the width of the resulting
// pillarbox, is determined by the height exponent of the aspect ratio.
// Therefore we multiply the width of the local camera view by the height
// ratio.
node.style.left = (offsetX - ((targetWidth * ratio.height) / 4)) + "px";
node.style.left = (offsetX - (realWidth * LOCAL_STREAM_OVERLAP)) + "px";
node.style.width = realWidth + "px";
node.style.height = realHeight + "px";
}
node.style.width = (targetWidth * ratio.width) + "px";
node.style.height = (targetWidth * ratio.height) + "px";
},
/**

Просмотреть файл

@ -295,30 +295,54 @@ loop.standaloneRoomViews = (function(mozL10n) {
* @param {Object} ratio Aspect ratio of the local camera stream
*/
updateLocalCameraPosition: function(ratio) {
// The local stream is a quarter of the remote stream.
var LOCAL_STREAM_SIZE = 0.25;
// The local stream overlaps the remote stream by a quarter of the local stream.
var LOCAL_STREAM_OVERLAP = 0.25;
// The minimum size of video height/width allowed by the sdk css.
var SDK_MIN_SIZE = 48;
var node = this._getElement(".local");
var parent = node.offsetParent || this._getElement(".media");
// The local camera view should be a sixth of the size of its offset parent
// and positioned to overlap with the remote stream at a quarter of its width.
var parentWidth = parent.offsetWidth;
var targetWidth = parentWidth / 6;
var targetWidth;
node.style.right = "auto";
if (window.matchMedia && window.matchMedia("screen and (max-width:640px)").matches) {
// For reduced screen widths, we just go for a fixed size and no overlap.
targetWidth = 180;
node.style.width = (targetWidth * ratio.width) + "px";
node.style.height = (targetWidth * ratio.height) + "px";
node.style.left = "auto";
} else {
// The local camera view should be a quarter of the size of the remote stream
// and positioned to overlap with the remote stream at a quarter of its width.
// Now position the local camera view correctly with respect to the remote
// video stream.
var remoteVideoDimensions = this.getRemoteVideoDimensions();
targetWidth = remoteVideoDimensions.streamWidth * LOCAL_STREAM_SIZE;
var realWidth = targetWidth * ratio.width;
var realHeight = targetWidth * ratio.height;
// If we've hit the min size limits, then limit at the minimum.
if (realWidth < SDK_MIN_SIZE) {
realWidth = SDK_MIN_SIZE;
realHeight = realWidth / ratio.width * ratio.height;
}
if (realHeight < SDK_MIN_SIZE) {
realHeight = SDK_MIN_SIZE;
realWidth = realHeight / ratio.height * ratio.width;
}
var offsetX = (remoteVideoDimensions.streamWidth + remoteVideoDimensions.offsetX);
// The horizontal offset of the stream, and the width of the resulting
// pillarbox, is determined by the height exponent of the aspect ratio.
// Therefore we multiply the width of the local camera view by the height
// ratio.
node.style.left = (offsetX - ((targetWidth * ratio.height) / 4)) + "px";
node.style.left = (offsetX - (realWidth * LOCAL_STREAM_OVERLAP)) + "px";
node.style.width = realWidth + "px";
node.style.height = realHeight + "px";
}
node.style.width = (targetWidth * ratio.width) + "px";
node.style.height = (targetWidth * ratio.height) + "px";
},
/**

Просмотреть файл

@ -143,6 +143,108 @@ describe("loop.standaloneRoomViews", function() {
});
});
describe("Local Stream Size Position", function() {
var view, localElement;
beforeEach(function() {
sandbox.stub(window, "matchMedia").returns({
matches: false
});
view = mountTestComponent();
localElement = view._getElement(".local");
});
it("should be a quarter of the width of the main stream", function() {
sandbox.stub(view, "getRemoteVideoDimensions").returns({
streamWidth: 640,
offsetX: 0
});
view.updateLocalCameraPosition({
width: 1,
height: 0.75
});
expect(localElement.style.width).eql("160px");
expect(localElement.style.height).eql("120px");
});
it("should be a quarter of the width reduced for aspect ratio", function() {
sandbox.stub(view, "getRemoteVideoDimensions").returns({
streamWidth: 640,
offsetX: 0
});
view.updateLocalCameraPosition({
width: 0.75,
height: 1
});
expect(localElement.style.width).eql("120px");
expect(localElement.style.height).eql("160px");
});
it("should ensure the height is a minimum of 48px", function() {
sandbox.stub(view, "getRemoteVideoDimensions").returns({
streamWidth: 180,
offsetX: 0
});
view.updateLocalCameraPosition({
width: 1,
height: 0.75
});
expect(localElement.style.width).eql("64px");
expect(localElement.style.height).eql("48px");
});
it("should ensure the width is a minimum of 48px", function() {
sandbox.stub(view, "getRemoteVideoDimensions").returns({
streamWidth: 180,
offsetX: 0
});
view.updateLocalCameraPosition({
width: 0.75,
height: 1
});
expect(localElement.style.width).eql("48px");
expect(localElement.style.height).eql("64px");
});
it("should position the stream to overlap the main stream by a quarter", function() {
sandbox.stub(view, "getRemoteVideoDimensions").returns({
streamWidth: 640,
offsetX: 0
});
view.updateLocalCameraPosition({
width: 1,
height: 0.75
});
expect(localElement.style.width).eql("160px");
expect(localElement.style.left).eql("600px");
});
it("should position the stream to overlap the main stream by a quarter when the aspect ratio is vertical", function() {
sandbox.stub(view, "getRemoteVideoDimensions").returns({
streamWidth: 640,
offsetX: 0
});
view.updateLocalCameraPosition({
width: 0.75,
height: 1
});
expect(localElement.style.width).eql("120px");
expect(localElement.style.left).eql("610px");
});
});
describe("#render", function() {
var view;