mirror of https://github.com/OpenVidu/openvidu.git
Recording layouts refactoring (prepare other layouts)
parent
984fd13374
commit
7cd9170d54
|
@ -1,23 +1,22 @@
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { FlexLayoutModule } from '@angular/flex-layout';
|
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
|
import { FlexLayoutModule } from '@angular/flex-layout';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { HttpModule } from '@angular/http';
|
import { HttpModule } from '@angular/http';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import 'hammerjs';
|
import 'hammerjs';
|
||||||
|
import { AppComponent } from './app.component';
|
||||||
import { routing } from './app.routing';
|
|
||||||
import { AppMaterialModule } from './app.material.module';
|
import { AppMaterialModule } from './app.material.module';
|
||||||
|
import { routing } from './app.routing';
|
||||||
|
import { CredentialsDialogComponent } from './components/dashboard/credentials-dialog.component';
|
||||||
|
import { DashboardComponent } from './components/dashboard/dashboard.component';
|
||||||
|
import { LayoutBestFitComponent } from './components/layouts/layout-best-fit/layout-best-fit.component';
|
||||||
|
import { LayoutHorizontalPresentationComponent } from './components/layouts/layout-horizontal-presentation/layout-horizontal-presentation.component';
|
||||||
|
import { LayoutVerticalPresentationComponent } from './components/layouts/layout-vertical-presentation/layout-vertical-presentation.component';
|
||||||
|
import { OpenViduVideoComponent } from './components/layouts/ov-video.component';
|
||||||
|
import { SessionDetailsComponent } from './components/session-details/session-details.component';
|
||||||
import { InfoService } from './services/info.service';
|
import { InfoService } from './services/info.service';
|
||||||
import { RestService } from './services/rest.service';
|
import { RestService } from './services/rest.service';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
|
||||||
import { DashboardComponent } from './components/dashboard/dashboard.component';
|
|
||||||
import { SessionDetailsComponent } from './components/session-details/session-details.component';
|
|
||||||
import { CredentialsDialogComponent } from './components/dashboard/credentials-dialog.component';
|
|
||||||
import { LayoutBestFitComponent } from './components/layouts/layout-best-fit/layout-best-fit.component';
|
|
||||||
import { OpenViduVideoComponent } from './components/layouts/ov-video.component';
|
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
AppComponent,
|
AppComponent,
|
||||||
|
@ -25,7 +24,9 @@ import { OpenViduVideoComponent } from './components/layouts/ov-video.component'
|
||||||
SessionDetailsComponent,
|
SessionDetailsComponent,
|
||||||
CredentialsDialogComponent,
|
CredentialsDialogComponent,
|
||||||
LayoutBestFitComponent,
|
LayoutBestFitComponent,
|
||||||
OpenViduVideoComponent,
|
LayoutVerticalPresentationComponent,
|
||||||
|
LayoutHorizontalPresentationComponent,
|
||||||
|
OpenViduVideoComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -36,7 +37,7 @@ import { OpenViduVideoComponent } from './components/layouts/ov-video.component'
|
||||||
FlexLayoutModule
|
FlexLayoutModule
|
||||||
],
|
],
|
||||||
entryComponents: [
|
entryComponents: [
|
||||||
CredentialsDialogComponent,
|
CredentialsDialogComponent
|
||||||
],
|
],
|
||||||
providers: [InfoService, RestService],
|
providers: [InfoService, RestService],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { ModuleWithProviders } from '@angular/core';
|
import { ModuleWithProviders } from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
|
||||||
import { DashboardComponent } from 'app/components/dashboard/dashboard.component';
|
import { DashboardComponent } from 'app/components/dashboard/dashboard.component';
|
||||||
import { SessionDetailsComponent } from 'app/components/session-details/session-details.component';
|
|
||||||
import { LayoutBestFitComponent } from 'app/components/layouts/layout-best-fit/layout-best-fit.component';
|
import { LayoutBestFitComponent } from 'app/components/layouts/layout-best-fit/layout-best-fit.component';
|
||||||
|
import { SessionDetailsComponent } from 'app/components/session-details/session-details.component';
|
||||||
|
import { LayoutHorizontalPresentationComponent } from './components/layouts/layout-horizontal-presentation/layout-horizontal-presentation.component';
|
||||||
|
import { LayoutVerticalPresentationComponent } from './components/layouts/layout-vertical-presentation/layout-vertical-presentation.component';
|
||||||
|
|
||||||
const appRoutes: Routes = [
|
const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
|
@ -21,6 +22,22 @@ const appRoutes: Routes = [
|
||||||
{
|
{
|
||||||
path: 'layout-best-fit/:sessionId/:secret/:onlyVideo',
|
path: 'layout-best-fit/:sessionId/:secret/:onlyVideo',
|
||||||
component: LayoutBestFitComponent
|
component: LayoutBestFitComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'layout-vertical-presentation/:sessionId/:secret',
|
||||||
|
component: LayoutVerticalPresentationComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'layout-vertical-presentation/:sessionId/:secret/:onlyVideo',
|
||||||
|
component: LayoutVerticalPresentationComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'layout-horizontal-presentation/:sessionId/:secret',
|
||||||
|
component: LayoutHorizontalPresentationComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'layout-horizontal-presentation/:sessionId/:secret/:onlyVideo',
|
||||||
|
component: LayoutHorizontalPresentationComponent
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
import { LayoutBestFitComponent } from './layout-best-fit.component';
|
import { LayoutBaseComponent } from './layout-base.component';
|
||||||
|
|
||||||
describe('SessionDetailsComponent', () => {
|
describe('LayoutBaseComponent', () => {
|
||||||
let component: LayoutBestFitComponent;
|
let component: LayoutBaseComponent;
|
||||||
let fixture: ComponentFixture<LayoutBestFitComponent>;
|
let fixture: ComponentFixture<LayoutBaseComponent>;
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [ LayoutBestFitComponent ]
|
declarations: [ LayoutBaseComponent ]
|
||||||
})
|
})
|
||||||
.compileComponents();
|
.compileComponents();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
fixture = TestBed.createComponent(LayoutBestFitComponent);
|
fixture = TestBed.createComponent(LayoutBaseComponent);
|
||||||
component = fixture.componentInstance;
|
component = fixture.componentInstance;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
});
|
});
|
|
@ -0,0 +1,148 @@
|
||||||
|
import {
|
||||||
|
ApplicationRef,
|
||||||
|
Component,
|
||||||
|
HostListener,
|
||||||
|
OnDestroy,
|
||||||
|
OnInit,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import {
|
||||||
|
OpenVidu,
|
||||||
|
Session,
|
||||||
|
StreamEvent,
|
||||||
|
StreamManagerEvent,
|
||||||
|
Subscriber
|
||||||
|
} from 'openvidu-browser';
|
||||||
|
import { OpenViduLayout, OpenViduLayoutOptions } from '../openvidu-layout';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-base',
|
||||||
|
templateUrl: './layout-base.component.html',
|
||||||
|
styleUrls: ['./layout-base.component.css'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class LayoutBaseComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
openviduLayout: OpenViduLayout;
|
||||||
|
sessionId: string;
|
||||||
|
secret: string;
|
||||||
|
onlyVideo = false;
|
||||||
|
|
||||||
|
session: Session;
|
||||||
|
subscribers: Subscriber[] = [];
|
||||||
|
|
||||||
|
layout: any;
|
||||||
|
resizeTimeout;
|
||||||
|
numberOfScreenStreams = 0;
|
||||||
|
|
||||||
|
layoutOptions: OpenViduLayoutOptions;
|
||||||
|
|
||||||
|
constructor(private route: ActivatedRoute, private appRef: ApplicationRef) {
|
||||||
|
this.route.params.subscribe(params => {
|
||||||
|
this.sessionId = params.sessionId;
|
||||||
|
this.secret = params.secret;
|
||||||
|
if (params.onlyVideo != null) {
|
||||||
|
this.onlyVideo = JSON.parse(params.onlyVideo);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:beforeunload')
|
||||||
|
beforeunloadHandler() {
|
||||||
|
this.leaveSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
sizeChange(event) {
|
||||||
|
clearTimeout(this.resizeTimeout);
|
||||||
|
this.resizeTimeout = setTimeout(() => {
|
||||||
|
this.openviduLayout.updateLayout();
|
||||||
|
}, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.leaveSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
const OV = new OpenVidu();
|
||||||
|
this.session = OV.initSession();
|
||||||
|
|
||||||
|
this.session.on('streamCreated', (event: StreamEvent) => {
|
||||||
|
if (!(this.onlyVideo && !event.stream.hasVideo)) {
|
||||||
|
let changeFixedRatio = false;
|
||||||
|
if (event.stream.typeOfVideo === 'SCREEN') {
|
||||||
|
this.numberOfScreenStreams++;
|
||||||
|
changeFixedRatio = true;
|
||||||
|
}
|
||||||
|
const subscriber: Subscriber = this.session.subscribe(
|
||||||
|
event.stream,
|
||||||
|
undefined,
|
||||||
|
{ subscribeToAudio: event.stream.hasAudio && !this.onlyVideo }
|
||||||
|
);
|
||||||
|
subscriber.on('streamPlaying', (e: StreamManagerEvent) => {
|
||||||
|
const video: HTMLVideoElement = subscriber.videos[0].video;
|
||||||
|
video.parentElement.parentElement.classList.remove('custom-class');
|
||||||
|
this.updateLayout(changeFixedRatio);
|
||||||
|
});
|
||||||
|
this.addSubscriber(subscriber);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.session.on('streamDestroyed', (event: StreamEvent) => {
|
||||||
|
let changeFixedRatio = false;
|
||||||
|
if (event.stream.typeOfVideo === 'SCREEN') {
|
||||||
|
this.numberOfScreenStreams--;
|
||||||
|
changeFixedRatio = true;
|
||||||
|
}
|
||||||
|
this.deleteSubscriber(<Subscriber>event.stream.streamManager);
|
||||||
|
this.updateLayout(changeFixedRatio);
|
||||||
|
});
|
||||||
|
|
||||||
|
const port = !!location.port ? (':' + location.port) : '';
|
||||||
|
const token = 'wss://' + location.hostname + port + '?sessionId=' + this.sessionId + '&secret=' + this.secret + '&recorder=true';
|
||||||
|
this.session.connect(token)
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error);
|
||||||
|
})
|
||||||
|
|
||||||
|
this.openviduLayout = new OpenViduLayout();
|
||||||
|
this.openviduLayout.initLayoutContainer(document.getElementById('layout'), this.layoutOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private addSubscriber(subscriber: Subscriber): void {
|
||||||
|
this.subscribers.push(subscriber);
|
||||||
|
this.appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
private deleteSubscriber(subscriber: Subscriber): void {
|
||||||
|
let index = -1;
|
||||||
|
for (let i = 0; i < this.subscribers.length; i++) {
|
||||||
|
if (this.subscribers[i] === subscriber) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index > -1) {
|
||||||
|
this.subscribers.splice(index, 1);
|
||||||
|
}
|
||||||
|
this.appRef.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
leaveSession() {
|
||||||
|
if (this.session) { this.session.disconnect(); };
|
||||||
|
this.subscribers = [];
|
||||||
|
this.session = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLayout(changeFixedRatio: boolean) {
|
||||||
|
if (changeFixedRatio) {
|
||||||
|
this.layoutOptions.fixedRatio = this.numberOfScreenStreams > 0;
|
||||||
|
this.openviduLayout.setLayoutOptions(this.layoutOptions);
|
||||||
|
}
|
||||||
|
this.openviduLayout.updateLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,28 +1,13 @@
|
||||||
import { Component, OnInit, OnDestroy, HostListener, ViewEncapsulation, ApplicationRef } from '@angular/core';
|
import { Component, ViewEncapsulation } from '@angular/core';
|
||||||
import { ActivatedRoute } from '@angular/router';
|
import { LayoutBaseComponent } from '../layout-base/layout-base.component';
|
||||||
import { OpenVidu, Session, Subscriber, StreamEvent, StreamManagerEvent } from 'openvidu-browser';
|
|
||||||
|
|
||||||
import { OpenViduLayout } from '../openvidu-layout';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-layout-best-fit',
|
selector: 'app-layout-best-fit',
|
||||||
templateUrl: './layout-best-fit.component.html',
|
templateUrl: '../layout-base/layout-base.component.html',
|
||||||
styleUrls: ['./layout-best-fit.component.css'],
|
styleUrls: ['../layout-base/layout-base.component.css'],
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class LayoutBestFitComponent implements OnInit, OnDestroy {
|
export class LayoutBestFitComponent extends LayoutBaseComponent {
|
||||||
|
|
||||||
openviduLayout: OpenViduLayout;
|
|
||||||
sessionId: string;
|
|
||||||
secret: string;
|
|
||||||
onlyVideo = false;
|
|
||||||
|
|
||||||
session: Session;
|
|
||||||
subscribers: Subscriber[] = [];
|
|
||||||
|
|
||||||
layout: any;
|
|
||||||
resizeTimeout;
|
|
||||||
numberOfScreenStreams = 0;
|
|
||||||
|
|
||||||
layoutOptions = {
|
layoutOptions = {
|
||||||
maxRatio: 3 / 2, // The narrowest ratio that will be used (default 2x3)
|
maxRatio: 3 / 2, // The narrowest ratio that will be used (default 2x3)
|
||||||
|
@ -35,113 +20,8 @@ export class LayoutBestFitComponent implements OnInit, OnDestroy {
|
||||||
bigMaxRatio: 3 / 2, // The narrowest ratio to use for the big elements (default 2x3)
|
bigMaxRatio: 3 / 2, // The narrowest ratio to use for the big elements (default 2x3)
|
||||||
bigMinRatio: 9 / 16, // The widest ratio to use for the big elements (default 16x9)
|
bigMinRatio: 9 / 16, // The widest ratio to use for the big elements (default 16x9)
|
||||||
bigFirst: true, // Whether to place the big one in the top left (true) or bottom right
|
bigFirst: true, // Whether to place the big one in the top left (true) or bottom right
|
||||||
animate: true // Whether you want to animate the transitions
|
animate: true, // Whether you want to animate the transitions
|
||||||
|
vertical: undefined // Whether to show small videos at the side or at the bottom
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute, private appRef: ApplicationRef) {
|
|
||||||
this.route.params.subscribe(params => {
|
|
||||||
this.sessionId = params.sessionId;
|
|
||||||
this.secret = params.secret;
|
|
||||||
if (params.onlyVideo !== null) {
|
|
||||||
this.onlyVideo = JSON.parse(params.onlyVideo);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('window:beforeunload')
|
|
||||||
beforeunloadHandler() {
|
|
||||||
this.leaveSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
|
||||||
sizeChange(event) {
|
|
||||||
clearTimeout(this.resizeTimeout);
|
|
||||||
this.resizeTimeout = setTimeout(() => {
|
|
||||||
this.openviduLayout.updateLayout();
|
|
||||||
}, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnDestroy() {
|
|
||||||
this.leaveSession();
|
|
||||||
}
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const OV = new OpenVidu();
|
|
||||||
this.session = OV.initSession();
|
|
||||||
|
|
||||||
this.session.on('streamCreated', (event: StreamEvent) => {
|
|
||||||
if (!(this.onlyVideo && !event.stream.hasVideo)) {
|
|
||||||
let changeFixedRatio = false;
|
|
||||||
if (event.stream.typeOfVideo === 'SCREEN') {
|
|
||||||
this.numberOfScreenStreams++;
|
|
||||||
changeFixedRatio = true;
|
|
||||||
}
|
|
||||||
const subscriber: Subscriber = this.session.subscribe(
|
|
||||||
event.stream,
|
|
||||||
undefined,
|
|
||||||
{ subscribeToAudio: event.stream.hasAudio && !this.onlyVideo }
|
|
||||||
);
|
|
||||||
subscriber.on('streamPlaying', (e: StreamManagerEvent) => {
|
|
||||||
const video: HTMLVideoElement = subscriber.videos[0].video;
|
|
||||||
video.parentElement.parentElement.classList.remove('custom-class');
|
|
||||||
this.updateLayout(changeFixedRatio);
|
|
||||||
});
|
|
||||||
this.addSubscriber(subscriber);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.session.on('streamDestroyed', (event: StreamEvent) => {
|
|
||||||
let changeFixedRatio = false;
|
|
||||||
if (event.stream.typeOfVideo === 'SCREEN') {
|
|
||||||
this.numberOfScreenStreams--;
|
|
||||||
changeFixedRatio = true;
|
|
||||||
}
|
|
||||||
this.deleteSubscriber(<Subscriber>event.stream.streamManager);
|
|
||||||
this.updateLayout(changeFixedRatio);
|
|
||||||
});
|
|
||||||
|
|
||||||
const port = !!location.port ? (':' + location.port) : '';
|
|
||||||
const token = 'wss://' + location.hostname + port + '?sessionId=' + this.sessionId + '&secret=' + this.secret + '&recorder=true';
|
|
||||||
this.session.connect(token)
|
|
||||||
.catch(error => {
|
|
||||||
console.error(error);
|
|
||||||
})
|
|
||||||
|
|
||||||
this.openviduLayout = new OpenViduLayout();
|
|
||||||
this.openviduLayout.initLayoutContainer(document.getElementById('layout'), this.layoutOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private addSubscriber(subscriber: Subscriber): void {
|
|
||||||
this.subscribers.push(subscriber);
|
|
||||||
this.appRef.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
private deleteSubscriber(subscriber: Subscriber): void {
|
|
||||||
let index = -1;
|
|
||||||
for (let i = 0; i < this.subscribers.length; i++) {
|
|
||||||
if (this.subscribers[i] === subscriber) {
|
|
||||||
index = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (index > -1) {
|
|
||||||
this.subscribers.splice(index, 1);
|
|
||||||
}
|
|
||||||
this.appRef.tick();
|
|
||||||
}
|
|
||||||
|
|
||||||
leaveSession() {
|
|
||||||
if (this.session) { this.session.disconnect(); };
|
|
||||||
this.subscribers = [];
|
|
||||||
this.session = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateLayout(changeFixedRatio: boolean) {
|
|
||||||
if (changeFixedRatio) {
|
|
||||||
this.layoutOptions.fixedRatio = this.numberOfScreenStreams > 0;
|
|
||||||
this.openviduLayout.setLayoutOptions(this.layoutOptions);
|
|
||||||
}
|
|
||||||
this.openviduLayout.updateLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
|
import { LayoutBaseComponent } from '../layout-base/layout-base.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-horizontal-presentation',
|
||||||
|
templateUrl: '../layout-base/layout-base.component.html',
|
||||||
|
styleUrls: ['../layout-base/layout-base.component.css'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class LayoutHorizontalPresentationComponent extends LayoutBaseComponent implements OnInit {
|
||||||
|
|
||||||
|
layoutOptions = {
|
||||||
|
maxRatio: 3 / 2, // The narrowest ratio that will be used (default 2x3)
|
||||||
|
minRatio: 9 / 16, // The widest ratio that will be used (default 16x9)
|
||||||
|
fixedRatio: false, /* If this is true then the aspect ratio of the video is maintained
|
||||||
|
and minRatio and maxRatio are ignored (default false) */
|
||||||
|
bigClass: 'OV_big', // The class to add to elements that should be sized bigger
|
||||||
|
bigPercentage: 0.8, // The maximum percentage of space the big ones should take up
|
||||||
|
bigFixedRatio: false, // fixedRatio for the big ones
|
||||||
|
bigMaxRatio: 3 / 2, // The narrowest ratio to use for the big elements (default 2x3)
|
||||||
|
bigMinRatio: 9 / 16, // The widest ratio to use for the big elements (default 16x9)
|
||||||
|
bigFirst: true, // Whether to place the big one in the top left (true) or bottom right
|
||||||
|
animate: true, // Whether you want to animate the transitions
|
||||||
|
vertical: false // Whether to show small videos at the side or at the bottom
|
||||||
|
};
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
super.ngOnInit();
|
||||||
|
this.session.on('signal:update-stream-layouts', event => {
|
||||||
|
// TODO: Add or remove class OV_big accordingly to each Subscriber video
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { Component, ViewEncapsulation, OnInit } from '@angular/core';
|
||||||
|
import { LayoutBaseComponent } from '../layout-base/layout-base.component';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-layout-vertical-presentation',
|
||||||
|
templateUrl: '../layout-base/layout-base.component.html',
|
||||||
|
styleUrls: ['../layout-base/layout-base.component.css'],
|
||||||
|
encapsulation: ViewEncapsulation.None
|
||||||
|
})
|
||||||
|
export class LayoutVerticalPresentationComponent extends LayoutBaseComponent implements OnInit {
|
||||||
|
|
||||||
|
layoutOptions = {
|
||||||
|
maxRatio: 3 / 2, // The narrowest ratio that will be used (default 2x3)
|
||||||
|
minRatio: 9 / 16, // The widest ratio that will be used (default 16x9)
|
||||||
|
fixedRatio: false, /* If this is true then the aspect ratio of the video is maintained
|
||||||
|
and minRatio and maxRatio are ignored (default false) */
|
||||||
|
bigClass: 'OV_big', // The class to add to elements that should be sized bigger
|
||||||
|
bigPercentage: 0.8, // The maximum percentage of space the big ones should take up
|
||||||
|
bigFixedRatio: false, // fixedRatio for the big ones
|
||||||
|
bigMaxRatio: 3 / 2, // The narrowest ratio to use for the big elements (default 2x3)
|
||||||
|
bigMinRatio: 9 / 16, // The widest ratio to use for the big elements (default 16x9)
|
||||||
|
bigFirst: false, // Whether to place the big one in the top left (true) or bottom right
|
||||||
|
animate: true, // Whether you want to animate the transitions
|
||||||
|
vertical: true // Whether to show small videos at the side or at the bottom
|
||||||
|
};
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
super.ngOnInit();
|
||||||
|
this.session.on('signal:update-stream-layouts', event => {
|
||||||
|
// TODO: Add or remove class OV_big accordingly to each Subscriber video
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -10,7 +10,8 @@ export interface OpenViduLayoutOptions {
|
||||||
bigFixedRatio: any;
|
bigFixedRatio: any;
|
||||||
bigMaxRatio: any;
|
bigMaxRatio: any;
|
||||||
bigMinRatio: any;
|
bigMinRatio: any;
|
||||||
bigFirst: any;
|
bigFirst: boolean;
|
||||||
|
vertical: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class OpenViduLayout {
|
export class OpenViduLayout {
|
||||||
|
@ -41,7 +42,7 @@ export class OpenViduLayout {
|
||||||
|
|
||||||
this.fixAspectRatio(elem, width);
|
this.fixAspectRatio(elem, width);
|
||||||
|
|
||||||
if (animate && $) {
|
if (!!animate && $) {
|
||||||
$(elem).stop();
|
$(elem).stop();
|
||||||
$(elem).animate(targetPosition, animate.duration || 200, animate.easing || 'swing',
|
$(elem).animate(targetPosition, animate.duration || 200, animate.easing || 'swing',
|
||||||
() => {
|
() => {
|
||||||
|
@ -296,21 +297,39 @@ export class OpenViduLayout {
|
||||||
if (bigOnes.length > 0 && smallOnes.length > 0) {
|
if (bigOnes.length > 0 && smallOnes.length > 0) {
|
||||||
let bigWidth, bigHeight;
|
let bigWidth, bigHeight;
|
||||||
|
|
||||||
if (availableRatio > this.getVideoRatio(bigOnes[0])) {
|
const horizontal = () => {
|
||||||
// We are tall, going to take up the whole width and arrange small
|
|
||||||
// guys at the bottom
|
|
||||||
bigWidth = WIDTH;
|
bigWidth = WIDTH;
|
||||||
bigHeight = Math.floor(HEIGHT * this.opts.bigPercentage);
|
bigHeight = Math.floor(HEIGHT * this.opts.bigPercentage);
|
||||||
offsetTop = bigHeight;
|
offsetTop = bigHeight;
|
||||||
bigOffsetTop = HEIGHT - offsetTop;
|
bigOffsetTop = HEIGHT - offsetTop;
|
||||||
} else {
|
}
|
||||||
// We are wide, going to take up the whole height and arrange the small
|
const vertical = () => {
|
||||||
// guys on the right
|
|
||||||
bigHeight = HEIGHT;
|
bigHeight = HEIGHT;
|
||||||
bigWidth = Math.floor(WIDTH * this.opts.bigPercentage);
|
bigWidth = Math.floor(WIDTH * this.opts.bigPercentage);
|
||||||
offsetLeft = bigWidth;
|
offsetLeft = bigWidth;
|
||||||
bigOffsetLeft = WIDTH - offsetLeft;
|
bigOffsetLeft = WIDTH - offsetLeft;
|
||||||
}
|
}
|
||||||
|
if (this.opts.vertical != null) {
|
||||||
|
if (!this.opts.vertical) {
|
||||||
|
// Horizontal presentation
|
||||||
|
horizontal();
|
||||||
|
} else {
|
||||||
|
// Vertical presentation
|
||||||
|
vertical();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Dynamic presentation
|
||||||
|
if (availableRatio > this.getVideoRatio(bigOnes[0])) {
|
||||||
|
// We are tall, going to take up the whole width and arrange small
|
||||||
|
// guys at the bottom
|
||||||
|
horizontal();
|
||||||
|
} else {
|
||||||
|
// We are wide, going to take up the whole height and arrange the small
|
||||||
|
// guys on the right
|
||||||
|
vertical();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.opts.bigFirst) {
|
if (this.opts.bigFirst) {
|
||||||
this.arrange(bigOnes, bigWidth, bigHeight, 0, 0, this.opts.bigFixedRatio, this.opts.bigMinRatio,
|
this.arrange(bigOnes, bigWidth, bigHeight, 0, 0, this.opts.bigFixedRatio, this.opts.bigMinRatio,
|
||||||
this.opts.bigMaxRatio, this.opts.animate);
|
this.opts.bigMaxRatio, this.opts.animate);
|
||||||
|
@ -344,7 +363,8 @@ export class OpenViduLayout {
|
||||||
bigFixedRatio: (opts.bigFixedRatio != null) ? opts.bigFixedRatio : false,
|
bigFixedRatio: (opts.bigFixedRatio != null) ? opts.bigFixedRatio : false,
|
||||||
bigMaxRatio: (opts.bigMaxRatio != null) ? opts.bigMaxRatio : 3 / 2,
|
bigMaxRatio: (opts.bigMaxRatio != null) ? opts.bigMaxRatio : 3 / 2,
|
||||||
bigMinRatio: (opts.bigMinRatio != null) ? opts.bigMinRatio : 9 / 16,
|
bigMinRatio: (opts.bigMinRatio != null) ? opts.bigMinRatio : 9 / 16,
|
||||||
bigFirst: (opts.bigFirst != null) ? opts.bigFirst : true
|
bigFirst: (opts.bigFirst != null) ? opts.bigFirst : true,
|
||||||
|
vertical: opts.vertical
|
||||||
};
|
};
|
||||||
this.layoutContainer = typeof (container) === 'string' ? $(container) : container;
|
this.layoutContainer = typeof (container) === 'string' ? $(container) : container;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue