参与视频通话已成为我们大多数在线体验的重要组成部分,以至于每周或每月花费多个小时参加它们。有了这种时间的投入,呼叫参与者可能会发现自己分心甚至需要多任务。尽管希望每个人在电话期间集中精力是合理的,但有时人们需要暂时将注意力转移。
开发人员有多种选择,可以帮助他们的最终用户避免在食用其他内容时失去视频通话的跟踪,例如:
- 使用Daily的picture-in-pip(PIP)设置。 (PIP使参与者在查看其他窗口时可以将视频弹出屏幕。)
- 即使在呼叫参与者浏览应用程序内容时,将视频通话保持在屏幕上。用CSS术语,这被称为“粘性” positioning或粘性标头。 后一种选项(粘性标头)是我们在今天的教程中关注的选择。
每天固定每日预构建的视频呼叫的每日演示。
粘性定位解决方案通常在包括视频播放器的应用中看到。例如,在新闻网站和社交媒体应用程序上,通常让用户滚动而不停止观看视频或在UI中失去跟踪的视频。
新闻网站的视频示例在滚动时留在屏幕上。
此功能允许用户将视频保留在页面上,同时仍然可以同时消费其他内容。
概述
在今天的教程中,我们将研究一种在仅使用CSS的视频呼叫应用程序中创建此粘性标题效果的一种方法。对于视频呼叫本身,我们将使用Daily Prebuilt,每天的视频呼叫UI可以嵌入任何只有几行代码的Web应用程序中。
我们将使用HTML,CSS和Plain JavaScript构建一个基本的Web应用程序。 (您将需要对这三个的介绍性理解才能跟随。)
演示应用程序将显示如何在用户向下滚动时将视频粘贴到页面顶部。粘性标头的代码很短(CSS两行!),因此我还提供一些附加的代码,以显示如何在粘贴在页面顶部时缩小视频调用UI。这两个功能(一个粘稠的标头和缩小的视频尺寸)经常在一起,因为用户通常希望视频在查看其他页面内容时占用更少的空间。
如果您在这里为CSS创建一个粘性标头,则是您需要的两行CSS:
.sticky-element {
position: sticky;
top: 0;
}
在本教程结束时,您将拥有一个使用一个HTML,一个CSS和一个JavaScript文件构建的网站,这将使您能够:
- jin a的地方:vania side quio: li>
- 在将视频呼叫放在屏幕上时,滚动浏览一些lorem ipsum Jeffsum文本。
过渡视频通话的大小,因此在滚动页面时,它较小,提供了更多的空间来读取呼叫下方的内容。
与大多数演示应用程序一样,您可能需要仔细调整实现以满足您自己的应用程序的需求。这里的想法是仅显示功能是什么及其工作方式的基本示例。
下面显示的所有示例代码都在GitHub中找到。随意分叉演示回购并随身携带。
最后,如果您想知道,可以在网络应用中滚出屏幕上的每日预构建视频通话,而不会对呼叫产生任何影响。呼叫不会结束,只是因为您滚动后可以看到它。今天的教程更多是要改善呼叫体验。
项目设置
如果您想在本地测试该项目,则可以克隆GitHub repository并使用以下终端命令进入本地副本:
git clone https://github.com/daily-demos/daily-samples-js.git
cd daily-samples-js/samples/daily-prebuilt/sticky-positioning/
要查看网站,请像这样打开index.html:
open ./index.html
项目结构
此演示应用中有三个主要文件:
- koude0:应用程序UI(用户界面)。
- koude1:客户端JavaScript代码处理文档scroll和submitting html表单等事件,我们将在下面创建。
- koude2:用户界面的样式,包括视频通话的粘附定位。
创建每日房间
要使用此演示,您将需要一个公共日常房间才能加入。
要获取每日室URL,create a Daily account。
有一个帐户并登录到Daily dashboard,您就可以create a new Daily room。
复制新房间的URL。您将在应用程序的联接表单中使用此值。您的每日房间URL应采用以下格式:
https://<your-daily-domain>.daily.co/<room-name>
设置index.html
文件
让我们开始查看渲染的主页应该启动的外观以及代表它的HTML代码。
主页,包括下面的联接表单和占位符文本。
我们的大多数应用程序都是占位符文本,可在视频通话中为用户提供一些内容以供阅读。本教程的重要HTML元素与日常呼叫有关:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Daily Prebuilt - Sticky positioning example</title>
/* Include daily-js */
<script src="https://unpkg.com/@daily-co/daily-js"></script>
<link rel="stylesheet" href="style.css" />
<script src="index.js"></script>
</head>
<body>
<main>
<h1>Daily Prebuilt - Sticky positioning example</h1>
<h2>Enter a Daily room URL to join a Daily call</h2>
/* Join form to join your Daily room. */
<form id="joinForm">
<label for="url">Room URL</label>
<input id="url" type="text" />
<input type="submit" value="Join room" />
</form>
/* Container for Daily Prebuilt to be embedded in. */
<div id="dailyContainer"></div>
<section>
/* Placeholder text section */
</section>
</main>
<footer>This is a footer.</footer>
</body>
</html>
上面的代码块中有三个主要部分:
- 我们在koude5 tag中包括的文件。那里的脚本标签包括koude6:
<script src="https://unpkg.com/@daily-co/daily-js"></script>
。这使我们可以在项目中访问每日客户sdk作为JavaScript。在此之下,还有index.js
和style.css
文件,这是我们将在其中工作的其他本地文件。 - koude10 element(我们的联接表格)。它有一个文本输入供用户输入他们的日常房间URL。注意:表格上还没有提交处理程序。我们将在
index.js
中添加。
- empty koude12 element带有ID
“dailyContainer”
,这是每日预构建的地方。该div
具有CSS style koude15;在style.css
文件中应用于它。我们只有在某人提交表格加入呼叫的表格后才显示。
本教程的其余部分将重点介绍应用我们的粘性标头和视频通话调整大小的CSS和JavaScript。
加入并显示视频通话
如前所述,在提交联接表格之前,不会显示视频调用的容器。让我们开始查看表单提交过程。
在koude1中,我们可以从添加一个表格submit event的事件处理程序:
let callFrame = null;
document.addEventListener('DOMContentLoaded', () => {
const joinForm = document.getElementById('joinForm');
const callContainer = document.getElementById('dailyContainer');
// ...
function createAndJoinCall(e) {
e.preventDefault();
// ...
}
joinForm.onsubmit = createAndJoinCall;
});
在此代码块中,callFrame
被声明为全局变量。稍后将在我们加入房间时,将分配每日call frame课程的实例。
加载DOM后,我们将检索呼叫容器div
和联接表单。这些用于设置JOIN表格的提交活动处理程序,并在后续代码中实例化每日呼叫框架。
现在,让我们看一下联接形式的submit
处理程序koude21中发生的情况:
function createAndJoinCall(e) {
e.preventDefault();
const dailyRoomUrl = e.target.url.value;
callFrame = window.DailyIframe.createFrame(callContainer);
callFrame.on('left-meeting', handleLeftMeeting);
// Hide the form and show the call container
joinForm.style.display = 'none';
callContainer.style.display = 'block';
try {
callFrame.join({
url: dailyRoomUrl,
showLeaveButton: true,
});
} catch (error) {
console.error(error);
}
}
在此功能中,第一步是调用e.preventDefault()
。这将防止表单提交触发页面刷新。
接下来,我们获得了每日房间URL的表单输入值:
const dailyRoomUrl = e.target.url.value;
然后,我们使用koude24工厂方法创建一个每日呼叫框架的新实例,并将callContainer
元素作为参数传递。这将导致每天嵌入callContainer
元素中的预构建。
创建了呼叫后,我们可以将回调附加到Daily的koude27事件。通过这样做,当本地参与者离开呼叫时,将调用回调函数(handleLeftMeeting())
。 (有关下面的更多信息。)
您可能想在应用程序中收听更多的Daily events,但是我们只需要在此演示中使用”left-meeting”
。
接下来,我们更新HTML元素以切换其显示;连接表单可以隐藏,可以显示呼叫容器,因为我们要加入呼叫。
最后,我们实际上可以使用koude30实例方法加入呼叫。我们从联接表格中检索到的每日房间URL用于指示我们要加入哪个房间,并且启用了koude31属性,可以为当地参与者提供一个无需关闭标签的方式。
。如果我们对此进行测试,现在可以提交我们的表格,并将被每日预构建代替,例如:
让我们简要看一下koude32:
function handleLeftMeeting() {
// Show the form and hide the call container
joinForm.style.display = 'block';
callContainer.style.display = 'none';
callFrame.destroy().then(() => {
callFrame = null;
});
}
当地参与者留下呼叫时,我们可以在加入时恢复我们切换的HTML元素的显示。连接表单再次显示,呼叫容器被隐藏。我们还在destroying呼叫框架本身之后重置callFrame
变量。这将我们的应用重置回原始状态。
为视频呼叫元素创建粘性标头效果
如上所述,粘性标头效应仅在koude2文件中使用两行CS创建:
#dailyContainer {
/* sticky header */
position: sticky;
top: 0;
/* end of sticky header*/
aspect-ratio: 16/12;
display: none; /* updated to block after joining */
width: 100%;
// ...
}
position:sticky;
表示,当元素达到top
属性的值时,该元素应粘贴。在这种情况下,top
设置为0
。这意味着,当#dailyContainer
处于y轴上的0px
或更小(即关闭屏幕)的滚动位置时,它应保持在0px的滚动位置。由于0px位于页面顶部,这将导致元素粘在顶部!
这里的其他CSS属性包括aspect-ratio
,它将维持视频呼叫元素的16:12比率。宽度属性意味着它将填充可用空间的100%
。
仅使用这些样式,我们已经有了这种效果:
视频粘贴在滚动时屏幕顶部,允许本地参与者在页面上查看其他内容而不会丢失通话。
这里的主要问题是,实际上没有足够的空间可以阅读以下内容。我们可以通过缩小视频呼叫元素在粘在顶部时来解决此问题。
更新视频呼叫元素的滚动大小
要实现在其粘性标头模式下缩小视频呼叫元素的目标,我们需要在两个斑点中添加代码:
-
koude2:我们将向呼叫容器元素的
width
添加过渡,并创建一个新的.scrolled
类以表示较小的尺寸。 -
koude1:我们将为文档的scroll event附加一个事件处理程序,并在确定应该较小的尺寸时,将新的
.scrolled
类添加到呼叫容器元素中。 从CSS开始,我们可以更新#dailyContainer
元素的样式:
#dailyContainer {
position: sticky;
top: 0;
aspect-ratio: 16/12;
display: none; /* updated to block after joining*/
width: 100%;
/* new styles to update the width and layout */
margin-left: auto;
transition-property: width;
transition-duration: 0.5s;
}
这三个新属性具有以下效果:
-
margin-left:auto;
意味着只要有额外的空间,就会将元素推到正确的位置。换句话说,当元素较小时,左边边缘将填充任何可用的空间。如果元素填补了空间(即,当width
为100%
时),则该声明对布局有任何影响。 -
transition-property
表示将应用于width
属性。 -
transition-duration
表示,当宽度过渡发生时,应该需要半秒钟才能完成。这使过渡更加顺畅,而不是在两种尺寸之间来回翻转。
接下来,让我们看一下我们将过渡到的大小,该尺寸在.scrolled
类中声明:
#dailyContainer.scrolled {
width: 60%;
}
这告诉我们,当将.scrolled
类添加到我们的呼叫容器div
中时,宽度应过渡到可用空间的60%。由于该元素已经具有纵横比集,因此高度将自动调整以适应新的宽度。
此外,当使用此功能时,margin-left
属性将通过将元素推向右侧对呼叫容器元素产生可见影响。
现在已经准备就绪CSS,让我们查看JavaScript代码,我们需要在滚动上应用此.scrolled
类。
使用文档scroll
事件更新视频呼叫的宽度
让我们开始查看与调整koude1中调用呼叫容器大小的JavaScript代码:
// Add the `scrolled` class when the window is scrolled
function handleScroll() {
// Scroll-handling logic here, which we’ll cover below
}
document.addEventListener("scroll", throttle(handleScroll, 140));
在此代码块中:
滚动事件在滚动时经常触发 - 与此功能工作所需的频率更高,这可能会对应用程序的性能产生负面影响 - 我们需要throttle调用handleScroll()
回调的频率。
为此,我们可以将handleScroll()
包装在koude67辅助功能中,该功能接受回调和数字作为参数。 (该数字代表应在调用回调之间等待的毫秒数。)在我们的情况下,它将等待100ms。
document.addEventListener("scroll", throttle(handleScroll, 100));
JavaScript
function throttle(func, timeFrame) {
var lastTime = 0;
return function () {
var now = new Date();
if (now - lastTime >= timeFrame) {
func();
lastTime = now;
}
};
}
让我们现在回顾koude62如何确定何时将.scrolled
类添加或删除到我们的视频容器元素中。
function handleScroll() {
const callContainer = document.getElementById('dailyContainer');
const notInCall = window.getComputedStyle(callContainer).display === 'none';
const { top } = callContainer.getBoundingClientRect(); // 0 (px) when scrolled and at the top of the screen.
const scrolled = callContainer.classList.contains('scrolled');
const threshold = 80; // px
// ...
}
首先,我们设置了一些变量,我们需要实现此功能:
- 我们将调用容器元素分配给变量:
callContainer
。 - 我们确定用户是否在呼叫中,因为,如果他们不恢复,我们不必担心滚动位置。我们通过查看呼叫容器的显示值等于
none
来做到这一点。 (回想:我们仅在提交联接表格后才显示呼叫容器。) - 然后,我们获得了
callContainer
的top
位置。当它是0
时,我们知道该文档已滚动,并且该呼叫现在位于屏幕的顶部。 - 我们确定呼叫容器是否已经具有
.scrolled
类。知道这将有助于我们确定是否需要添加或删除它。 - 我们声明一个
threshold
变量,该变量将代表一个限制(以像素为单位),在该限制可以移动而无需再次更新它。这很有用,因为当视频呼叫在滚动上进行调整时,它将稍微改变top
位置。它需要能够在不触发另一个大小的情况下移动一点。否则,如果它滚动到调整大小发生的坐标时,它可能会进入调整循环。
接下来,我们可以使用这些值来确定何时应用.scrolled
类:
function handleScroll() {
// ...Variables described above
// Don't apply scroll logic when the local participant isn't in the call.
if (notInCall) return;
// Don't update the class list if it's already marked correctly for its placement.
if ((scrolled && top === 0) || (!scrolled && top > 0)) return;
// Remove scrolled class if it's scrolled back up.
if (scrolled && top > threshold) {
callContainer.classList.remove('scrolled');
}
// Add scrolled class otherwise.
else {
callContainer.classList.add('scrolled');
}
}
以下发生在上面的块中:
- 如果没有显示呼叫,请提早返回。无需其他动作。
- 如果已经根据需要应用
.scrolled
类(即,由于页面被滚动或排除,因为页面没有滚动,因此应用了),请提早返回。我们的预期CSS已经应用。 - 如果将呼叫容器标记为滚动到顶部,但是容器的顶部位置大于我们的阈值值,我们可以删除
.scrolled
类。当将视频呼叫固定在页面顶部时,top
将等于0
,因此,如果它比80
(像素)高,我们可以肯定地说它不再处于顶部。 - 在最后的情况下,我们可以添加我们的
.scrolled
类。呼叫容器没有标记为滚动,但我们确定它在顶部。
这样,我们的过渡现在将起作用,因为.scrolled
类将在滚动上应用(或删除),并且呼叫容器的CSS width
属性将相应更新。
如您所见,在阈值以前的区域中上下滚动没有影响。只有当您越过过渡的阈值时,才是:
结论
在当今的教程中,我们查看了几行CSS,这些CS可以添加到您的每日预构建实现中,即使您应用程序用户向下滚动,也可以使其保持在屏幕上。
我们还研究了当用户滚动以提供更多空间以读取呼叫下方的内容时,如何更改呼叫容器的大小。
要了解有关每日预构建的有关构建的更多信息,请在每日博客上阅读我们的其他一些教程,以及我们的日常预制指南。
要看到另一个可以让本地参与者的视频动作的每日演示,请参阅我们的Electron series,以构建视频通话作为覆盖层,包括视频拖放功能。