...
Code Block |
---|
|
const createOneToOneParticipantView = function () {
const participantDiv = createContainer(null);
const audioDisplay = createContainer(participantDiv);
const participantNicknameDisplay = createInfoDisplay(participantDiv, "Name: ")
const videoPlayers = new Map();
const audioElements = new Map();
return {
rootDiv: participantDiv,
dispose: function () {
for (const player of videoPlayers.values()) {
...
},
addVideoTrack: player.dispose();function (track) {
}...
videoPlayers.clear();},
removeVideoTrack: function (track) {
for (const element of audioElements.values()) {
...
},
element.remove();
addVideoSource: function (remoteVideoTrack, track, onResize, muteHandler) }{
audioElements.clear();...
},
addVideoTrackremoveVideoSource: function (track) {
...
const player = createVideoPlayer(participantDiv); },
showVideoTrack: function (track) {
videoPlayers..set(track.mid, player);
},
removeVideoTrackaddAudioTrack: function (track, audioTrack, show) {
const player = videoPlayers.get(track.mid);...
if (player) {},
removeAudioTrack: player.dispose();function (track) {
}...
},
addVideoSourcesetNickname: function (remoteVideoTrackuserId, track, onResize, muteHandlernickname) {
const player = videoPlayers.get(track.mid);...
if (player) {},
player.setVideoSource(remoteVideoTrack, onResize, muteHandler);updateQuality: function (track, qualityName, available) {
}...
},
removeVideoSourceaddQuality: function (track, qualityName, available, onQualityPick) {
const player = videoPlayers.get(track.mid);...
if (player) {},
pickQuality: function (track, player.removeVideoSource();qualityName) {
}...
},
}
} |
10.1. Добавление видео дорожки
addVideoTrack() code
Code Block |
---|
|
const createOneToOneParticipantView = showVideoTrack: function (track) {
...
return {
const player = videoPlayers..get(track.mid);
ifaddVideoTrack: function (playertrack) {
const player = player.showVideoTrack(trackcreateVideoPlayer(participantDiv);
} videoPlayers.set(track.mid, player);
},
...
addAudioTrack: }
} |
10.2. Удаление видео дорожки
removeVideoTrack() code
Code Block |
---|
|
const createOneToOneParticipantView = function (track, audioTrack, show) {
...
return {
const stream = new MediaStream(); ...
removeVideoTrack: function stream.addTrack(audioTracktrack); {
const audioElementplayer = documentvideoPlayers.createElement("audio"get(track.mid);
if (!showplayer) {
hideItemplayer.dispose(audioElement);
}
},
audioElement...controls
= "controls";
}
} |
10.3. Добавление источника к видео элементу
addVideoSource() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
audioElement...muted
= true;
return {
audioElement.autoplay = true;...
addVideoSource: function (remoteVideoTrack, audioElement.onloadedmetadata = function (etrack, onResize, muteHandler) {
const player = audioElementvideoPlayers.playget().then(function () {
track.mid);
if (Browser().isSafariWebRTC() && Browser().isiOS()) player) {
console.warn("Audio track should be manually unmuted in iOS Safari"player.setVideoSource(remoteVideoTrack, onResize, muteHandler);
}
} else {,
...
}
} |
10.4. Удаление источника из видео элемента
removeVideoSource() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
audioElement.muted = false;return {
...
removeVideoSource: function (track) }{
const player }= videoPlayers.get(track.mid);
};
if (player) {
audioElements.set(track.mid, audioElement);
audioDisplay.appendChild(audioElementplayer.removeVideoSource();
audioElement.srcObject = stream;}
},
...
removeAudioTrack: }
} |
10.5. Показать видео дорожку
showVideoTrack() code
Code Block |
---|
|
const createOneToOneParticipantView = function (track) {
...
return {
const audioElement = audioElements..get(track.mid);
ifshowVideoTrack: function (audioElementtrack) {
const player = audioElementvideoPlayers.removeget(track.mid);
if audioElements.delete(track.mid);(player) {
}
player.showVideoTrack(track);
},
}
setNickname: function (userId, nickname) {
},
...
}
} |
10.6. Добавление аудио дорожки
addAudioTrack() code
Code Block |
---|
|
const additionalUserIdcreateOneToOneParticipantView = userId ? "#" + getShortUserId(userId) : "";function () {
participantNicknameDisplay.innerText = "Name: " + nickname + additionalUserId;...
return {
},...
updateQualityaddAudioTrack: function (track, qualityNameaudioTrack, availableshow) {
const playerstream = videoPlayers.get(track.midnew MediaStream();
if (player) {stream.addTrack(audioTrack);
const audioElement = playerdocument.updateQuality(qualityName, availablecreateElement("audio");
}
if (!show) {
},
hideItem(audioElement);
addQuality: function (track, qualityName, available, onQualityPick) {}
const playeraudioElement.controls = videoPlayers.get(track.mid)"controls";
if (player) {audioElement.muted = true;
audioElement.autoplay = true;
player.addQuality(qualityName, available, onQualityPick);
audioElement.onloadedmetadata = function (e) }{
},
pickQuality: audioElement.play().then(function (track, qualityName) {
const player = videoPlayers.get(track.mid);if (Browser().isSafariWebRTC() && Browser().isiOS()) {
if (player) {
console.warn("Audio track should be manually unmuted in player.pickQuality(qualityNameiOS Safari");
}
} else {
audioElement.muted = false;
}
});
};
audioElements.set(track.mid, audioElement);
audioDisplay.appendChild(audioElement);
audioElement.srcObject = stream;
},
...
}
} |
10.7. Удаление аудио дорожки
removeAudioTrack() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
return {
...
removeAudioTrack: function (track) {
const audioElement = audioElements.get(track.mid);
if (audioElement) {
audioElement.remove();
audioElements.delete(track.mid);
}
},
...
}
} |
10.8. Отображение имени участника
setNickname() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
return {
...
setNickname: function (userId, nickname) {
const additionalUserId = userId ? "#" + getShortUserId(userId) : "";
participantNicknameDisplay.innerText = "Name: " + nickname + additionalUserId;
},
...
}
} |
10.9. Обновление информации о качестве
updateQuality() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
return {
...
updateQuality: function (track, qualityName, available) {
const player = videoPlayers.get(track.mid);
if (player) {
player.updateQuality(qualityName, available);
}
},
...
}
} |
10.10. Добавление информации о качестве
addQuality() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
return {
...
addQuality: function (track, qualityName, available, onQualityPick) {
const player = videoPlayers.get(track.mid);
if (player) {
player.addQuality(qualityName, available, onQualityPick);
}
},
...
}
} |
10.11. Выбор качества
pickQuality() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
return {
...
pickQuality: function (track, qualityName) {
const player = videoPlayers.get(track.mid);
if (player) {
player.pickQuality(qualityName);
}
}
...
}
} |
10.12. Завершение отображения
dispose() code
Code Block |
---|
|
const createOneToOneParticipantView = function () {
...
return {
...
dispose: function () {
for (const player of videoPlayers.values()) {
player.dispose();
}
videoPlayers.clear();
for (const element of audioElements.values()) {
element.remove();
}
audioElements.clear();
},
...
}
} |
11. Создание объекта отображения участника в комнате с несколькими участниками
createOneToManyParticipantView() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
const participantDiv = createContainer(null);
const audioDisplay = createContainer(participantDiv);
const participantNicknameDisplay = createInfoDisplay(participantDiv, "Name: ")
const audioElements = new Map();
const player = createVideoPlayer(participantDiv);
return {
rootDiv: participantDiv,
currentTrack: null,
dispose: function () {
...
},
addVideoTrack: function (track) {
...
},
removeVideoTrack: function (track) {
...
},
addVideoSource: function (remoteVideoTrack, track, onResize, muteHandler) {
...
},
removeVideoSource: function (track) {
...
},
showVideoTrack: function (track) {
...
},
addAudioTrack: function (track, audioTrack, show) {
...
},
removeAudioTrack: function (track) {
...
},
setNickname: function (userId, nickname) {
...
},
updateQuality: function (track, qualityName, available) {
...
},
addQuality: function (track, qualityName, available, onQualityPick) {
...
},
clearQualityState: function (track) {
...
},
pickQuality: function (track, qualityName) {
...
}
}
} |
11.1. Добавление видео дорожки
addVideoTrack() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
addVideoTrack: function (track, requestVideoTrack) {
player.addVideoTrack(track, async () => {
return requestVideoTrack();
});
},
...
}
} |
11.2. Удаление видео дорожки
removeVideoTrack() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
removeVideoTrack: function (track) {
player.removeVideoTrack(track);
},
...
}
} |
11.3. Добавление источника к видео элементу
addVideoSource() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
addVideoSource: function (remoteVideoTrack, track, onResize, muteHandler) {
this.currentTrack = track;
player.setVideoSource(remoteVideoTrack, onResize, muteHandler);
},
...
}
} |
11.4. Удаление источника из видео элемента
removeVideoSource() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
removeVideoSource: function (track) {
if (this.currentTrack && this.currentTrack.mid === track.mid) {
player.removeVideoSource();
}
},
...
}
} |
11.5. Показать видео дорожку
showVideoTrack() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
showVideoTrack: function (track) {
player.showVideoTrack(track);
},
...
}
} |
11.6. Добавление аудио дорожки
addAudioTrack() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
addAudioTrack: function (track, audioTrack, show) {
const stream = new MediaStream();
stream.addTrack(audioTrack);
const audioElement = document.createElement("audio");
if (!show) {
hideItem(audioElement);
}
audioElement.controls = "controls";
audioElement.muted = true;
audioElement.autoplay = true;
audioElement.onloadedmetadata = function (e) {
audioElement.play().then(function () {
if (Browser().isSafariWebRTC() && Browser().isiOS()) {
console.warn("Audio track should be manually unmuted in iOS Safari");
} else {
audioElement.muted = false;
}
});
};
audioElements.set(track.mid, audioElement);
audioDisplay.appendChild(audioElement);
audioElement.srcObject = stream;
},
...
}
} |
11.7. Удаление аудио дорожки
removeAudioTrack() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
removeAudioTrack: function (track) {
const audioElement = audioElements.get(track.mid);
if (audioElement) {
audioElement.remove();
audioElements.delete(track.mid);
}
},
...
}
} |
11.8. Отображение имени участника
setNickname() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
setNickname: function (userId, nickname) {
const additionalUserId = userId ? "#" + getShortUserId(userId) : "";
participantNicknameDisplay.innerText = "Name: " + nickname + additionalUserId;
},
...
}
} |
11.9. Обновление информации о качестве
updateQuality() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
updateQuality: function (track, qualityName, available) {
player.updateQuality(qualityName, available);
},
...
}
} |
11.10. Добавление информации о качестве
addQuality() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
addQuality: function (track, qualityName, available, onQualityPick) {
player.addQuality(qualityName, available, onQualityPick);
},
...
}
} |
11.11. Выбор качества
pickQuality() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
pickQuality: function (track, qualityName) {
player.pickQuality(qualityName);
}
...
}
} |
11.12. Очистка отображаемого списка качеств
clearQualityState() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
clearQualityState: function (track) {
player.clearQualityState();
},
...
}
} |
11.13. Завершение отображения
dispose() code
Code Block |
---|
|
const createOneToManyParticipantView = function () {
...
return {
...
dispose: function () {
player.dispose();
for (const element of audioElements.values()) {
element.remove();
}
audioElements.clear();
},
...
}
} |
12. Создание объекта видео плеера
createVideoPlayer() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
const streamDisplay = createContainer(participantDiv);
const resolutionLabel = createInfoDisplay(streamDisplay, "0x0");
hideItem(resolutionLabel);
const trackNameDisplay = createInfoDisplay(streamDisplay, "track not set");
hideItem(trackNameDisplay);
const videoMuteDisplay = createContainer(streamDisplay);
const qualityDisplay = createContainer(streamDisplay);
const trackDisplay = createContainer(streamDisplay);
let videoElement;
const trackButtons = new Map();
const qualityButtons = new Map();
const lock = function () {
...
}
const unlock = function () {
...
}
const setWebkitEventHandlers = function (video) {
...
}
const setEventHandlers = function (video) {
...
}
const repickQuality = function (qualityName) {
...
}
return {
rootDiv: streamDisplay,
muteButton: null,
autoButton: null,
dispose: function () {
...
},
clearQualityState: function () {
...
},
addVideoTrack: function (track, asyncCallback) {
...
},
removeVideoTrack: function (track) {
...
},
setVideoSource: function (remoteVideoTrack, onResize, onMute) {
...
},
removeVideoSource: function () {
...
},
showVideoTrack: function (track) {
...
},
updateQuality: function (qualityName, available) {
...
},
addQuality: function (qualityName, available, onPickQuality) {
...
},
pickQuality: function (qualityName) {
...
}
}
} |
12.1. Блокировка и разблокировка кнопок плеера для асинхронных операций
lock(), unlock() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
const lock = function () {
for (const btn of trackButtons.values()) {
btn.disabled = true;
}
for (const state of qualityButtons.values()) {
state.btn.disabled = true;
}
}
const unlock = function () {
for (const btn of trackButtons.values()) {
btn.disabled = false;
}
for (const state of qualityButtons.values()) {
state.btn.disabled = false;
}
}
...
return {
...
}
} |
12.2. Настройка обработчиков событий плеера для Safari
setWebkitEventHandlers() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
const setWebkitEventHandlers = function (video) {
let needRestart = false;
let isFullscreen = false;
// Use webkitbeginfullscreen event to detect full screen mode in iOS Safari
video.addEventListener("webkitbeginfullscreen", function () {
isFullscreen = true;
});
video.addEventListener("pause", function () {
if (needRestart) {
console.log("Media paused after fullscreen, continue...");
video.play();
needRestart = false;
} else {
console.log("Media paused by click, continue...");
video.play();
}
});
video.addEventListener("webkitendfullscreen", function () {
video.play();
needRestart = true;
isFullscreen = false;
});
}
...
return {
...
}
} |
12.3. Настройка обработчиков событий плеера для других браузеров
setEventHandlers() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
const setEventHandlers = function (video) {
// Ignore play/pause button
video.addEventListener("pause", function () {
console.log("Media paused by click, continue...");
video.play();
});
}
...
return {
...
}
} |
12.4. Перерисовка кнопок переключения качества
repickQuality() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
const repickQuality = function (qualityName) {
for (const [quality, state] of qualityButtons.entries()) {
if (quality === qualityName) {
state.btn.style.color = QUALITY_COLORS.SELECTED;
} else if (state.btn.style.color === QUALITY_COLORS.SELECTED) {
if (state.available) {
state.btn.style.color = QUALITY_COLORS.AVAILABLE;
} else {
state.btn.style.color = QUALITY_COLORS.UNAVAILABLE;
}
}
}
}
...
return {
...
}
} |
12.5. Удаление кнопок переключения качества
clearQualityState() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
clearQualityState: function () {
qualityButtons.forEach((state, qName) => {
state.btn.remove();
});
qualityButtons.clear();
},
...
}
} |
12.6. Добавление видео дорожки
addVideoTrack() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
addVideoTrack: function (track, asyncCallback) {
const trackButton = document.createElement("button");
trackButtons.set(track.mid, trackButton);
trackButton.innerText = "Track №" + track.mid + ": " + track.contentType;
trackButton.setAttribute("style", "display:inline-block; border: solid; border-width: 1px");
trackButton.style.color = QUALITY_COLORS.AVAILABLE;
const self = this;
trackButton.addEventListener('click', async function () {
console.log("Clicked on track button track.mid " + track.mid);
if (trackButton.style.color === QUALITY_COLORS.SELECTED) {
return
}
lock();
asyncCallback().then(() => {
self.showVideoTrack(track);
}).finally(() => {
unlock();
});
});
trackDisplay.appendChild(trackButton);
},
...
}
} |
12.7. Удаление видео дорожки
removeVideoTrack() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
removeVideoTrack: function (track) {
const trackButton = trackButtons.get(track.mid);
if (trackButton) {
trackButton.remove();
trackButtons.delete(track.mid);
}
},
...
}
} |
12.8. Добавление видео элемента и назначение видео дорожки как источника проигрывания
setVideoSource() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
setVideoSource: function (remoteVideoTrack, onResize, onMute) {
if (!this.muteButton) {
const newVideoMuteBtn = document.createElement("button");
this.muteButton = newVideoMuteBtn;
newVideoMuteBtn.innerText = "mute";
newVideoMuteBtn.setAttribute("style", "display:inline-block; border: solid; border-width: 1px");
newVideoMuteBtn.addEventListener('click', async function () {
newVideoMuteBtn.disabled = true;
try {
if (newVideoMuteBtn.innerText === "mute") {
await onMute(true);
newVideoMuteBtn.innerText = "unmute";
} else if (newVideoMuteBtn.innerText === "unmute") {
await onMute(false);
newVideoMuteBtn.innerText = "mute";
}
} finally {
newVideoMuteBtn.disabled = false;
}
});
videoMuteDisplay.appendChild(newVideoMuteBtn);
}
if (videoElement) {
videoElement.remove();
videoElement = null;
}
if (!remoteVideoTrack) {
return;
}
videoElement = document.createElement("video");
hideItem(videoElement);
videoElement.setAttribute("style", "display:none; border: solid; border-width: 1px");
const stream = new MediaStream();
streamDisplay.appendChild(videoElement);
videoElement.srcObject = stream;
videoElement.onloadedmetadata = function (e) {
videoElement.play();
};
videoElement.addEventListener("resize", function (event) {
showItem(resolutionLabel);
if (videoElement) {
resolutionLabel.innerText = videoElement.videoWidth + "x" + videoElement.videoHeight;
resizeVideo(event.target);
onResize();
}
});
stream.addTrack(remoteVideoTrack);
if (Browser().isSafariWebRTC()) {
videoElement.setAttribute("playsinline", "");
videoElement.setAttribute("webkit-playsinline", "");
setWebkitEventHandlers(videoElement);
} else {
setEventHandlers(videoElement);
}
},
...
}
} |
12.9. Удаление видео элемента
removeVideoSource() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
removeVideoSource: function () {
if (videoElement) {
videoElement.remove();
videoElement = null;
}
if (this.muteButton) {
this.muteButton.remove();
this.muteButton = null;
}
hideItem(resolutionLabel);
trackNameDisplay.innerText = "track not set";
},
...
}
} |
12.10. Отображение видео элемента и информации о видео дорожке
showVideoTrack() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
showVideoTrack: function (track) {
if (videoElement) {
showItem(videoElement);
}
for (const [mid, btn] of trackButtons.entries()) {
if (mid === track.mid) {
btn.style.color = QUALITY_COLORS.SELECTED;
} else if (btn.style.color === QUALITY_COLORS.SELECTED) {
btn.style.color = QUALITY_COLORS.AVAILABLE;
}
}
trackNameDisplay.innerText = "Current video track: " + track.mid;
showItem(trackNameDisplay);
},
...
}
} |
12.11. Обновление информации о качестве
updateQuality() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
updateQuality: function (qualityName, available) {
const value = qualityButtons.get(qualityName);
if (value) {
const qualityButton = value.btn;
value.available = available;
if (qualityButton.style.color === QUALITY_COLORS.SELECTED) {
return;
}
if (available) {
qualityButton.style.color = QUALITY_COLORS.AVAILABLE;
} else {
qualityButton.style.color = QUALITY_COLORS.UNAVAILABLE;
}
}
},
...
}
} |
12.12. Добавление кнопки выбора качества
addQuality() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
addQuality: function (qualityName, available, onPickQuality) {
const qualityButton = document.createElement("button");
qualityButtons.set(qualityName, {btn: qualityButton, available: available});
qualityButton.innerText = qualityName;
qualityButton.setAttribute("style", "display:inline-block; border: solid; border-width: 1px");
if (available) {
qualityButton.style.color = QUALITY_COLORS.AVAILABLE;
} else {
qualityButton.style.color = QUALITY_COLORS.UNAVAILABLE;
}
qualityDisplay.appendChild(qualityButton);
qualityButton.addEventListener('click', async function () {
console.log("Clicked on quality button " + qualityName);
if (qualityButton.style.color === QUALITY_COLORS.SELECTED || qualityButton.style.color === QUALITY_COLORS.UNAVAILABLE || !videoElement) {
return;
}
lock();
onPickQuality().finally(() => unlock());
});
},
...
}
} |
12.13. Нажатие на кнопку выбора качества
pickQuality() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
pickQuality: function (qualityName) {
repickQuality(qualityName);
}
...
}
} |
12.14. Завершение работы плеера
dispose() code
Code Block |
---|
|
const createVideoPlayer = function (participantDiv) {
...
return {
...
dispose: function () {
streamDisplay.remove();
},
...
}
} |
13. Получение дорожки из комнаты для отображения
remoteTrackProvider() code
Code Block |
---|
|
const remoteTrackProvider = function (room) {
return {
getVideoTrack: async function () {
return await room.getRemoteTrack("VIDEO", false);
},
getAudioTrack: async function () {
return await room.getRemoteTrack("AUDIO", true);
}
}
} |
14. Вспомогательные функции
14.1. Изменение размера видео под размеры плеера
resizeVideo(), downScaleToFitSize() code
Code Block |
---|
|
const resizeVideo = function (video, width, height) {
// TODO: fix
if (video) {
return;
}
if (!video.parentNode) {
return;
}
if (video instanceof HTMLCanvasElement) {
video.videoWidth = video.width;
video.videoHeight = video.height;
}
const display = video.parentNode;
const parentSize = {
w: display.parentNode.clientWidth,
h: display.parentNode.clientHeight
};
let newSize;
if (width && height) {
newSize = downScaleToFitSize(width, height, parentSize.w, parentSize.h);
} else {
newSize = downScaleToFitSize(video.videoWidth, video.videoHeight, parentSize.w, parentSize.h);
}
display.style.width = newSize.w + "px";
display.style.height = newSize.h + "px";
//vertical align
let margin = 0;
if (parentSize.h - newSize.h > 1) {
margin = Math.floor((parentSize.h - newSize.h) / 2);
}
display.style.margin = margin + "px auto";
console.log("Resize from " + video.videoWidth + "x" + video.videoHeight + " to " + display.offsetWidth + "x" + display.offsetHeight);
}
const downScaleToFitSize = function (videoWidth, videoHeight, dstWidth, dstHeight) {
var newWidth, newHeight;
var videoRatio = videoWidth / videoHeight;
var dstRatio = dstWidth / dstHeight;
if (dstRatio > videoRatio) {
newHeight = dstHeight;
newWidth = Math.floor(videoRatio * dstHeight);
} else {
newWidth = dstWidth;
newHeight = Math.floor(dstWidth / videoRatio);
}
return {
w: newWidth,
h: newHeight
};
} |
14.2. Создание элемента для отображения текстовой информации
createInfoDisplay() code
Code Block |
---|
|
const createInfoDisplay = function (parent, text) {
const div = document.createElement("div");
if (text) {
div.innerHTML = text;
}
div.setAttribute("style", "width:auto; height:30px;");
div.setAttribute("class", "text-center");
if (parent) {
parent.appendChild(div);
}
return div;
} |
14.3. Создание элемента-контейнера
createContainer() code
Code Block |
---|
|
const createContainer = function (parent) {
const div = document.createElement("div");
div.setAttribute("style", "width:auto; height:auto;");
div.setAttribute("class", "text-center");
if (parent) {
parent.appendChild(div);
}
return div;
} |
14.4. Скрытие и отображение элемента на странице
showItem(), hideItem() code
Code Block |
---|
|
const showItem = function (tag) {
if (tag) {
tag.style.display = "block";
}
}
const hideItem = function (tag) {
if (tag) {
tag.style.display = "none";
}
} |