Changing the way we focus a video element.
Now, only one video element can be important.
This commit is contained in:
parent
ac7fa164b6
commit
5cf5e0ce2b
@ -1,5 +1,6 @@
|
|||||||
<script lang="typescript">
|
<script lang="typescript">
|
||||||
import {ScreenSharingLocalMedia} from "../../Stores/ScreenSharingStore";
|
import {ScreenSharingLocalMedia} from "../../Stores/ScreenSharingStore";
|
||||||
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
function srcObject(node, stream) {
|
function srcObject(node, stream) {
|
||||||
node.srcObject = stream;
|
node.srcObject = stream;
|
||||||
@ -18,6 +19,6 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
<div class="video-container {cssClass}" class:hide={!stream}>
|
<div class="video-container {cssClass ? cssClass : ''}" class:hide={!stream}>
|
||||||
<video class="myCamVideo" use:srcObject={stream} autoplay muted playsinline on:click={() => peer.importanceStore.toggle()}></video>
|
<video use:srcObject={stream} autoplay muted playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {ScreenSharingPeer} from "../../WebRtc/ScreenSharingPeer";
|
import {ScreenSharingPeer} from "../../WebRtc/ScreenSharingPeer";
|
||||||
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
export let peer: ScreenSharingPeer;
|
export let peer: ScreenSharingPeer;
|
||||||
let streamStore = peer.streamStore;
|
let streamStore = peer.streamStore;
|
||||||
@ -45,7 +46,7 @@
|
|||||||
{#if $streamStore === null}
|
{#if $streamStore === null}
|
||||||
<i style="background-color: {getColorByString(name)};">{name}</i>
|
<i style="background-color: {getColorByString(name)};">{name}</i>
|
||||||
{/if}
|
{/if}
|
||||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => peer.importanceStore.toggle()}></video>
|
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
import reportImg from "./images/report.svg";
|
import reportImg from "./images/report.svg";
|
||||||
import blockSignImg from "./images/blockSign.svg";
|
import blockSignImg from "./images/blockSign.svg";
|
||||||
import {DivImportance} from "../../WebRtc/LayoutManager";
|
import {DivImportance} from "../../WebRtc/LayoutManager";
|
||||||
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
export let peer: VideoPeer;
|
export let peer: VideoPeer;
|
||||||
let streamStore = peer.streamStore;
|
let streamStore = peer.streamStore;
|
||||||
let name = peer.userName;
|
let name = peer.userName;
|
||||||
let statusStore = peer.statusStore;
|
let statusStore = peer.statusStore;
|
||||||
let constraintStore = peer.constraintsStore;
|
let constraintStore = peer.constraintsStore;
|
||||||
let importanceStore = peer.importanceStore;
|
|
||||||
|
|
||||||
constraintStore.subscribe((vl) => console.log('CONS', vl));
|
constraintStore.subscribe((vl) => console.log('CONS', vl));
|
||||||
|
|
||||||
@ -62,17 +62,10 @@
|
|||||||
<img alt="Report this user" src={reportImg}>
|
<img alt="Report this user" src={reportImg}>
|
||||||
<span>Report/Block</span>
|
<span>Report/Block</span>
|
||||||
</button>
|
</button>
|
||||||
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => peer.importanceStore.toggle()}></video>
|
<video use:srcObject={$streamStore} autoplay playsinline on:click={() => videoFocusStore.toggleFocus(peer)}></video>
|
||||||
<img src={blockSignImg} class="block-logo" alt="Block">
|
<img src={blockSignImg} class="block-logo" alt="Block">
|
||||||
{#if $constraintStore && $constraintStore.audio !== false}
|
{#if $constraintStore && $constraintStore.audio !== false}
|
||||||
<SoundMeterWidget stream={$streamStore}></SoundMeterWidget>
|
<SoundMeterWidget stream={$streamStore}></SoundMeterWidget>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.video-container {
|
|
||||||
video {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
@ -3,18 +3,23 @@
|
|||||||
import {DivImportance} from "../../WebRtc/LayoutManager";
|
import {DivImportance} from "../../WebRtc/LayoutManager";
|
||||||
import Peer from "./Peer.svelte";
|
import Peer from "./Peer.svelte";
|
||||||
import {layoutStore} from "../../Stores/LayoutStore";
|
import {layoutStore} from "../../Stores/LayoutStore";
|
||||||
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="video-overlay">
|
<div class="video-overlay">
|
||||||
<div class="main-section">
|
<div class="main-section">
|
||||||
{#each [...$layoutStore.get(DivImportance.Important).values()] as peer (peer.uniqueId)}
|
{#each [...$layoutStore.values()] as peer (peer.uniqueId)}
|
||||||
<Peer peer={peer}></Peer>
|
{#if $videoFocusStore && peer === $videoFocusStore }
|
||||||
|
<Peer peer={peer}></Peer>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
<aside class="sidebar">
|
<aside class="sidebar">
|
||||||
{#each [...$layoutStore.get(DivImportance.Normal).values()] as peer (peer.uniqueId)}
|
{#each [...$layoutStore.values()] as peer (peer.uniqueId)}
|
||||||
<Peer peer={peer}></Peer>
|
{#if peer !== $videoFocusStore }
|
||||||
|
<Peer peer={peer}></Peer>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</aside>
|
</aside>
|
||||||
<div class="chat-mode three-col" style="display: none;">
|
<div class="chat-mode three-col" style="display: none;">
|
||||||
|
@ -95,6 +95,7 @@ import {DEPTH_OVERLAY_INDEX} from "./DepthIndexes";
|
|||||||
import {waScaleManager} from "../Services/WaScaleManager";
|
import {waScaleManager} from "../Services/WaScaleManager";
|
||||||
import {peerStore, screenSharingPeerStore} from "../../Stores/PeerStore";
|
import {peerStore, screenSharingPeerStore} from "../../Stores/PeerStore";
|
||||||
import {EmoteManager} from "./EmoteManager";
|
import {EmoteManager} from "./EmoteManager";
|
||||||
|
import {videoFocusStore} from "../../Stores/VideoFocusStore";
|
||||||
|
|
||||||
export interface GameSceneInitInterface {
|
export interface GameSceneInitInterface {
|
||||||
initPosition: PointInterface|null,
|
initPosition: PointInterface|null,
|
||||||
@ -647,6 +648,7 @@ export class GameScene extends DirtyScene implements CenterListener {
|
|||||||
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic, this.playerName);
|
this.simplePeer = new SimplePeer(this.connection, !this.room.isPublic, this.playerName);
|
||||||
peerStore.connectToSimplePeer(this.simplePeer);
|
peerStore.connectToSimplePeer(this.simplePeer);
|
||||||
screenSharingPeerStore.connectToSimplePeer(this.simplePeer);
|
screenSharingPeerStore.connectToSimplePeer(this.simplePeer);
|
||||||
|
videoFocusStore.connectToSimplePeer(this.simplePeer);
|
||||||
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
|
this.GlobalMessageManager = new GlobalMessageManager(this.connection);
|
||||||
userMessageManager.setReceiveBanListener(this.bannedUser.bind(this));
|
userMessageManager.setReceiveBanListener(this.bannedUser.bind(this));
|
||||||
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
import {VideoPeer} from "../WebRtc/VideoPeer";
|
|
||||||
import {Subscriber, Unsubscriber, writable} from "svelte/store";
|
|
||||||
import {RemotePeer, SimplePeer} from "../WebRtc/SimplePeer";
|
|
||||||
import {DivImportance} from "../WebRtc/LayoutManager";
|
|
||||||
|
|
||||||
export interface ImportanceStore {
|
|
||||||
subscribe: (this:void, run: Subscriber<DivImportance>, invalidate?: ((value?: DivImportance) => void | undefined)) => Unsubscriber,
|
|
||||||
toggle: () => void,
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createImportanceStore(defaultImportance: DivImportance): ImportanceStore {
|
|
||||||
const { subscribe, set, update } = writable<DivImportance>(defaultImportance);
|
|
||||||
|
|
||||||
return {
|
|
||||||
subscribe,
|
|
||||||
toggle: () => {
|
|
||||||
update((importance) => {
|
|
||||||
if (importance === DivImportance.Important) {
|
|
||||||
return DivImportance.Normal;
|
|
||||||
} else {
|
|
||||||
return DivImportance.Important;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
import {derived, get} from "svelte/store";
|
import {derived, get, writable} from "svelte/store";
|
||||||
import {ScreenSharingLocalMedia, screenSharingLocalMedia} from "./ScreenSharingStore";
|
import {ScreenSharingLocalMedia, screenSharingLocalMedia} from "./ScreenSharingStore";
|
||||||
import {DivImportance} from "../WebRtc/LayoutManager";
|
|
||||||
import { peerStore, screenSharingStreamStore} from "./PeerStore";
|
import { peerStore, screenSharingStreamStore} from "./PeerStore";
|
||||||
import type {RemotePeer} from "../WebRtc/SimplePeer";
|
import type {RemotePeer} from "../WebRtc/SimplePeer";
|
||||||
|
|
||||||
@ -27,26 +26,15 @@ function createLayoutStore() {
|
|||||||
}
|
}
|
||||||
unsubscribes = [];
|
unsubscribes = [];
|
||||||
|
|
||||||
const peers = new Map<DivImportance, Map<string, DisplayableMedia>>();
|
const peers = new Map<string, DisplayableMedia>();
|
||||||
peers.set(DivImportance.Normal, new Map<string, DisplayableMedia>());
|
|
||||||
peers.set(DivImportance.Important, new Map<string, DisplayableMedia>());
|
|
||||||
|
|
||||||
const addPeer = (peer: DisplayableMedia) => {
|
const addPeer = (peer: DisplayableMedia) => {
|
||||||
const importance = get(peer.importanceStore);
|
peers.set(peer.uniqueId, peer);
|
||||||
|
|
||||||
peers.get(importance)?.set(peer.uniqueId, peer);
|
|
||||||
|
|
||||||
unsubscribes.push(peer.importanceStore.subscribe((importance) => {
|
|
||||||
peers.forEach((category) => {
|
|
||||||
category.delete(peer.uniqueId);
|
|
||||||
});
|
|
||||||
peers.get(importance)?.set(peer.uniqueId, peer);
|
|
||||||
set(peers);
|
|
||||||
}));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
$screenSharingStreamStore.forEach(addPeer);
|
$screenSharingStreamStore.forEach(addPeer);
|
||||||
$peerStore.forEach(addPeer);
|
$peerStore.forEach(addPeer);
|
||||||
|
|
||||||
if ($screenSharingLocalMedia?.stream) {
|
if ($screenSharingLocalMedia?.stream) {
|
||||||
addPeer($screenSharingLocalMedia);
|
addPeer($screenSharingLocalMedia);
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import type {
|
|||||||
} from "./MediaStore";
|
} from "./MediaStore";
|
||||||
import {DivImportance} from "../WebRtc/LayoutManager";
|
import {DivImportance} from "../WebRtc/LayoutManager";
|
||||||
import {gameOverlayVisibilityStore} from "./GameOverlayStoreVisibility";
|
import {gameOverlayVisibilityStore} from "./GameOverlayStoreVisibility";
|
||||||
import {createImportanceStore, ImportanceStore} from "./ImportanceStore";
|
|
||||||
|
|
||||||
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
declare const navigator:any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
|
|
||||||
@ -189,7 +188,6 @@ export const screenSharingAvailableStore = derived(peerStore, ($peerStore, set)
|
|||||||
|
|
||||||
export interface ScreenSharingLocalMedia {
|
export interface ScreenSharingLocalMedia {
|
||||||
uniqueId: string;
|
uniqueId: string;
|
||||||
importanceStore: ImportanceStore;
|
|
||||||
stream: MediaStream|null;
|
stream: MediaStream|null;
|
||||||
//subscribe(this: void, run: Subscriber<ScreenSharingLocalMedia>, invalidate?: (value?: ScreenSharingLocalMedia) => void): Unsubscriber;
|
//subscribe(this: void, run: Subscriber<ScreenSharingLocalMedia>, invalidate?: (value?: ScreenSharingLocalMedia) => void): Unsubscriber;
|
||||||
}
|
}
|
||||||
@ -201,7 +199,6 @@ export const screenSharingLocalMedia = readable<ScreenSharingLocalMedia|null>(nu
|
|||||||
|
|
||||||
const localMedia: ScreenSharingLocalMedia = {
|
const localMedia: ScreenSharingLocalMedia = {
|
||||||
uniqueId: "localScreenSharingStream",
|
uniqueId: "localScreenSharingStream",
|
||||||
importanceStore: createImportanceStore(DivImportance.Normal),
|
|
||||||
stream: null
|
stream: null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
48
front/src/Stores/VideoFocusStore.ts
Normal file
48
front/src/Stores/VideoFocusStore.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import {writable} from "svelte/store";
|
||||||
|
import type {RemotePeer, SimplePeer} from "../WebRtc/SimplePeer";
|
||||||
|
import {VideoPeer} from "../WebRtc/VideoPeer";
|
||||||
|
import {ScreenSharingPeer} from "../WebRtc/ScreenSharingPeer";
|
||||||
|
import type {DisplayableMedia} from "./LayoutStore";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store that contains the peer / media that has currently the "importance" focus.
|
||||||
|
*/
|
||||||
|
function createVideoFocusStore() {
|
||||||
|
const { subscribe, set, update } = writable<DisplayableMedia | null>(null);
|
||||||
|
|
||||||
|
let focusedMedia: DisplayableMedia | null = null;
|
||||||
|
|
||||||
|
return {
|
||||||
|
subscribe,
|
||||||
|
focus: (media: DisplayableMedia) => {
|
||||||
|
focusedMedia = media;
|
||||||
|
set(media);
|
||||||
|
},
|
||||||
|
removeFocus: () => {
|
||||||
|
focusedMedia = null;
|
||||||
|
set(null);
|
||||||
|
},
|
||||||
|
toggleFocus: (media: DisplayableMedia) => {
|
||||||
|
if (media !== focusedMedia) {
|
||||||
|
focusedMedia = media;
|
||||||
|
} else {
|
||||||
|
focusedMedia = null;
|
||||||
|
}
|
||||||
|
console.log('MEDIA', focusedMedia)
|
||||||
|
set(focusedMedia);
|
||||||
|
},
|
||||||
|
connectToSimplePeer: (simplePeer: SimplePeer) => {
|
||||||
|
simplePeer.registerPeerConnectionListener({
|
||||||
|
onConnect(peer: RemotePeer) {
|
||||||
|
},
|
||||||
|
onDisconnect(userId: number) {
|
||||||
|
if ((focusedMedia instanceof VideoPeer || focusedMedia instanceof ScreenSharingPeer) && focusedMedia.userId === userId) {
|
||||||
|
set(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export const videoFocusStore = createVideoFocusStore();
|
@ -5,9 +5,7 @@ import type {RoomConnection} from "../Connexion/RoomConnection";
|
|||||||
import {MESSAGE_TYPE_CONSTRAINT} from "./VideoPeer";
|
import {MESSAGE_TYPE_CONSTRAINT} from "./VideoPeer";
|
||||||
import type {UserSimplePeerInterface} from "./SimplePeer";
|
import type {UserSimplePeerInterface} from "./SimplePeer";
|
||||||
import {Readable, readable, writable, Writable} from "svelte/store";
|
import {Readable, readable, writable, Writable} from "svelte/store";
|
||||||
import {DivImportance} from "./LayoutManager";
|
import {videoFocusStore} from "../Stores/VideoFocusStore";
|
||||||
import type {ImportanceStore} from "../Stores/ImportanceStore";
|
|
||||||
import {createImportanceStore} from "../Stores/ImportanceStore";
|
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
@ -24,7 +22,6 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
public readonly userId: number;
|
public readonly userId: number;
|
||||||
public readonly uniqueId: string;
|
public readonly uniqueId: string;
|
||||||
public readonly streamStore: Readable<MediaStream | null>;
|
public readonly streamStore: Readable<MediaStream | null>;
|
||||||
public readonly importanceStore: ImportanceStore;
|
|
||||||
public readonly statusStore: Readable<"connecting" | "connected" | "error" | "closed">;
|
public readonly statusStore: Readable<"connecting" | "connected" | "error" | "closed">;
|
||||||
|
|
||||||
constructor(user: UserSimplePeerInterface, initiator: boolean, public readonly userName: string, private connection: RoomConnection, stream: MediaStream | null) {
|
constructor(user: UserSimplePeerInterface, initiator: boolean, public readonly userName: string, private connection: RoomConnection, stream: MediaStream | null) {
|
||||||
@ -50,6 +47,7 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
|
|
||||||
this.streamStore = readable<MediaStream|null>(null, (set) => {
|
this.streamStore = readable<MediaStream|null>(null, (set) => {
|
||||||
const onStream = (stream: MediaStream|null) => {
|
const onStream = (stream: MediaStream|null) => {
|
||||||
|
videoFocusStore.focus(this);
|
||||||
set(stream);
|
set(stream);
|
||||||
};
|
};
|
||||||
const onData = (chunk: Buffer) => {
|
const onData = (chunk: Buffer) => {
|
||||||
@ -73,8 +71,6 @@ export class ScreenSharingPeer extends Peer {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
this.importanceStore = createImportanceStore(DivImportance.Important);
|
|
||||||
|
|
||||||
this.statusStore = readable<"connecting" | "connected" | "error" | "closed">("connecting", (set) => {
|
this.statusStore = readable<"connecting" | "connected" | "error" | "closed">("connecting", (set) => {
|
||||||
const onConnect = () => {
|
const onConnect = () => {
|
||||||
set('connected');
|
set('connected');
|
||||||
|
@ -5,11 +5,9 @@ import type {RoomConnection} from "../Connexion/RoomConnection";
|
|||||||
import {blackListManager} from "./BlackListManager";
|
import {blackListManager} from "./BlackListManager";
|
||||||
import type {Subscription} from "rxjs";
|
import type {Subscription} from "rxjs";
|
||||||
import type {UserSimplePeerInterface} from "./SimplePeer";
|
import type {UserSimplePeerInterface} from "./SimplePeer";
|
||||||
import {get, readable, Readable, writable, Writable} from "svelte/store";
|
import {get, readable, Readable} from "svelte/store";
|
||||||
import {obtainedMediaConstraintStore} from "../Stores/MediaStore";
|
import {obtainedMediaConstraintStore} from "../Stores/MediaStore";
|
||||||
import {DivImportance} from "./LayoutManager";
|
import {DivImportance} from "./LayoutManager";
|
||||||
import type {ImportanceStore} from "../Stores/ImportanceStore";
|
|
||||||
import {createImportanceStore} from "../Stores/ImportanceStore";
|
|
||||||
|
|
||||||
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
const Peer: SimplePeerNamespace.SimplePeer = require('simple-peer');
|
||||||
|
|
||||||
@ -30,7 +28,6 @@ export class VideoPeer extends Peer {
|
|||||||
private onBlockSubscribe: Subscription;
|
private onBlockSubscribe: Subscription;
|
||||||
private onUnBlockSubscribe: Subscription;
|
private onUnBlockSubscribe: Subscription;
|
||||||
public readonly streamStore: Readable<MediaStream | null>;
|
public readonly streamStore: Readable<MediaStream | null>;
|
||||||
public readonly importanceStore: ImportanceStore;
|
|
||||||
public readonly statusStore: Readable<"connecting" | "connected" | "error" | "closed">;
|
public readonly statusStore: Readable<"connecting" | "connected" | "error" | "closed">;
|
||||||
public readonly constraintsStore: Readable<MediaStreamConstraints|null>;
|
public readonly constraintsStore: Readable<MediaStreamConstraints|null>;
|
||||||
|
|
||||||
@ -94,8 +91,6 @@ export class VideoPeer extends Peer {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
this.importanceStore = createImportanceStore(DivImportance.Normal);
|
|
||||||
|
|
||||||
this.statusStore = readable<"connecting" | "connected" | "error" | "closed">("connecting", (set) => {
|
this.statusStore = readable<"connecting" | "connected" | "error" | "closed">("connecting", (set) => {
|
||||||
const onConnect = () => {
|
const onConnect = () => {
|
||||||
set('connected');
|
set('connected');
|
||||||
|
@ -35,102 +35,108 @@ body .message-info.info{
|
|||||||
body .message-info.warning{
|
body .message-info.warning{
|
||||||
background: #ffa500d6;
|
background: #ffa500d6;
|
||||||
}
|
}
|
||||||
.video-container{
|
|
||||||
|
.video-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
background-color: #00000099;
|
background-color: #00000099;
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
}
|
|
||||||
.video-container i{
|
|
||||||
position: absolute;
|
|
||||||
width: 100px;
|
|
||||||
height: 100px;
|
|
||||||
left: calc(50% - 50px);
|
|
||||||
top: calc(50% - 50px);
|
|
||||||
background-color: black;
|
|
||||||
border-radius: 50%;
|
|
||||||
text-align: center;
|
|
||||||
padding-top: 32px;
|
|
||||||
font-size: 28px;
|
|
||||||
color: white;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container img{
|
video {
|
||||||
position: absolute;
|
width: 100%;
|
||||||
display: none;
|
height: 100%;
|
||||||
width: 40px;
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
height: 40px;
|
}
|
||||||
left: 5px;
|
|
||||||
bottom: 5px;
|
|
||||||
padding: 10px;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
.video-container img.block-logo {
|
|
||||||
left: 30%;
|
|
||||||
bottom: 15%;
|
|
||||||
width: 150px;
|
|
||||||
height: 150px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container button.report{
|
i {
|
||||||
display: block;
|
position: absolute;
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
width: 100px;
|
||||||
background: none;
|
height: 100px;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
left: calc(50% - 50px);
|
||||||
border: none;
|
top: calc(50% - 50px);
|
||||||
background-color: black;
|
background-color: black;
|
||||||
border-radius: 15px;
|
border-radius: 50%;
|
||||||
position: absolute;
|
text-align: center;
|
||||||
width: 0px;
|
padding-top: 32px;
|
||||||
height: 35px;
|
font-size: 28px;
|
||||||
right: 5px;
|
color: white;
|
||||||
bottom: 5px;
|
overflow: hidden;
|
||||||
padding: 0px;
|
}
|
||||||
overflow: hidden;
|
|
||||||
z-index: 2;
|
|
||||||
transition: all .5s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container:hover button.report{
|
img {
|
||||||
width: 35px;
|
position: absolute;
|
||||||
padding: 10px;
|
display: none;
|
||||||
}
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
left: 5px;
|
||||||
|
bottom: 5px;
|
||||||
|
padding: 10px;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
.video-container button.report:hover {
|
img.block-logo {
|
||||||
width: 160px;
|
left: 30%;
|
||||||
}
|
bottom: 15%;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
.video-container button.report img{
|
button.report{
|
||||||
position: absolute;
|
display: block;
|
||||||
display: block;
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
bottom: 5px;
|
background: none;
|
||||||
left: 5px;
|
background-color: rgba(0, 0, 0, 0);
|
||||||
margin: 0;
|
border: none;
|
||||||
padding: 0;
|
background-color: black;
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
border-radius: 15px;
|
||||||
width: 25px;
|
position: absolute;
|
||||||
height: 25px;
|
width: 0px;
|
||||||
}
|
height: 35px;
|
||||||
.video-container button.report span{
|
right: 5px;
|
||||||
position: absolute;
|
bottom: 5px;
|
||||||
bottom: 6px;
|
padding: 0px;
|
||||||
left: 36px;
|
overflow: hidden;
|
||||||
color: white;
|
z-index: 2;
|
||||||
font-size: 16px;
|
transition: all .5s ease;
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
|
||||||
}
|
|
||||||
.video-container img.active {
|
|
||||||
display: block !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-container video{
|
img{
|
||||||
height: 100%;
|
position: absolute;
|
||||||
cursor: url('./images/cursor_pointer.png'), pointer;
|
display: block;
|
||||||
}
|
bottom: 5px;
|
||||||
|
left: 5px;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
.video-container video:focus{
|
span {
|
||||||
outline: none;
|
position: absolute;
|
||||||
|
bottom: 6px;
|
||||||
|
left: 36px;
|
||||||
|
color: white;
|
||||||
|
font-size: 16px;
|
||||||
|
cursor: url('./images/cursor_pointer.png'), pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
img.active {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover button.report{
|
||||||
|
width: 35px;
|
||||||
|
padding: 10px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
video:focus{
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.video-container.div-myCamVideo{
|
.video-container.div-myCamVideo{
|
||||||
|
Loading…
Reference in New Issue
Block a user