如何创建 YouTube 克隆版。使用 HTML、CSS、JS 创建 YouTube 克隆版。
视频教程
代码
最后一件事 - 搜索框
您可能觉得有用的文章
您好,欢迎!今天我们将学习如何仅使用 HTML、CSS 和 JS 轻松创建一个 YouTube 克隆版本,无需其他库。我们还将使用 YouTube API 从 YouTube 获取真实数据。
我们的克隆版有很多功能。比如,它看起来像 YouTube。所有视频数据都直接来自 YouTube。我们还提供了可用的搜索栏,可以将用户重定向到 YouTube 官方搜索页面。而且,每当用户点击视频卡时,他/她都会被重定向到 YouTube 的官方视频页面。
如果您想观看演示或完整的编码教程视频,可以观看下面的教程。
视频教程
因此,不要浪费更多时间,让我们看看如何编写代码。
代码
首先,这个项目有 3 个文件index.html
,style.css
和app.js
。我们使用非常基础的 CSS,所以我不会详细解释每个 CSS 属性。但是,如果您有任何疑问,请随时在评论区提问。我们将理解每一行 JavaScript。
首先让我们创建导航栏。我们的导航栏 HTML 结构。
<nav class="navbar">
<div class="toggle-btn">
<span></span>
<span></span>
<span></span>
</div>
<img src="img/logo.PNG" class="logo" alt="">
<div class="search-box">
<input type="text" class="search-bar" placeholder="search">
<button class="search-btn"><img src="img/search.PNG" alt=""></button>
</div>
<div class="user-options">
<img src="img/video.PNG" class="icon" alt="">
<img src="img/grid.PNG" class="icon" alt="">
<img src="img/bell.PNG" class="icon" alt="">
<div class="user-dp">
<img src="img/profile-pic.png" alt="">
</div>
</div>
</nav>
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
*:focus{
outline: none;
}
body{
position: relative;
background: #f0f0f0;
font-family: 'roboto', sans-serif;
}
.navbar{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 60px;
background: #fff;
display: flex;
align-items: center;
padding: 0 2.5vw;
}
.toggle-btn{
width: 20px;
height: 10px;
position: relative;
cursor: pointer;
}
.toggle-btn span{
position: absolute;
width: 100%;
height: 2px;
top: 50%;
transform: translateY(-50%);
background: #979797;
}
.toggle-btn span:nth-child(1){
top: 0;
}
.toggle-btn span:nth-child(3){
top: 100%;
}
.logo{
height: 30px;
margin: -10px 30px 0;
}
.search-box{
position: relative;
max-width: 500px;
width: 50%;
height: 35px;
display: flex;
}
.search-bar{
width: 85%;
height: 100%;
border: 2px solid #dbdbdb;
padding: 0 20px;
font-size: 16px;
text-transform: capitalize;
}
.search-btn{
width: 15%;
height: 100%;
background: #f0f0f0;
border: 2px solid #dbdbdb;
padding: 5px 0;
border-left: none;
}
.search-btn img{
height: 100%;
}
.user-options{
height: 35px;
display: flex;
margin-left: auto;
align-items: center;
}
.user-options .icon{
height: 80%;
margin-right: 20px;
cursor: pointer;
}
.user-dp{
cursor: pointer;
height: 30px;
width: 30px;
border-radius: 50%;
overflow: hidden;
}
.user-dp img{
width: 100%;
height: 100%;
object-fit: cover;
}
现在创建侧边导航栏。
<div class="side-bar">
<a href="#" class="links active"><img src="img/home.PNG" alt="">home</a>
<a href="#" class="links"><img src="img/explore.PNG" alt="">explore</a>
<a href="#" class="links"><img src="img/subscription.PNG" alt="">subscription</a>
<hr class="seperator">
<a href="#" class="links"><img src="img/library.PNG" alt="">library</a>
<a href="#" class="links"><img src="img/history.PNG" alt="">history</a>
<a href="#" class="links"><img src="img/your-video.PNG" alt="">your video</a>
<a href="#" class="links"><img src="img/watch-later.PNG" alt="">watch leater</a>
<a href="#" class="links"><img src="img/liked video.PNG" alt="">like video</a>
<a href="#" class="links"><img src="img/show more.PNG" alt="">show more</a>
</div>
CSS
.side-bar{
position: fixed;
top: 60px;
left: 0;
min-width: 250px;
width: 250px;
height: calc(100vh - 60px);
background: #fff;
padding-right: 10px;
}
.links{
display: block;
width: 100%;
padding: 10px 20px;
display: flex;
align-items: center;
text-transform: capitalize;
color: #242424;
font-size: 14px;
font-weight: 500;
text-decoration: none;
}
.links img{
height: 25px;
margin-right: 20px;
}
.links:hover,
.links.active{
background: rgba(0, 0, 0, 0.1);
}
.seperator{
border: none;
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
margin: 20px 0;
}
现在,过滤器选项
<div class="filters">
<button class="filter-options active">all</button>
<button class="filter-options">CSS</button>
<button class="filter-options">web development</button>
<button class="filter-options">python</button>
<button class="filter-options">entertainment</button>
<button class="filter-options">marvel</button>
<button class="filter-options">javascript</button>
<button class="filter-options">artificial intelligence</button>
<button class="filter-options">machine learning</button>
<button class="filter-options">trending</button>
</div>
CSS
.filters{
position: fixed;
left: 250px;
top: 60px;
width: calc(100% - 250px);
height: 60px;
background: #fff;
border-top: 1px solid #dbdbdb;
border-bottom: 1px solid #dbdbdb;
padding: 0 20px;
display: flex;
align-items: center;
overflow-x: auto;
overflow-y: hidden;
}
.filters::-webkit-scrollbar{
display: none;
}
.filter-options{
flex: 0 0 auto;
padding: 10px 20px;
border-radius: 50px;
background: #f0f0f0;
border: 1px solid #dbdbdb;
text-transform: capitalize;
margin-right: 10px;
color: #242424;
font-size: 15px;
cursor: pointer;
}
.filter-options.active{
color: #fff;
background: #242424;
}
现在到了最后也是最重要的事情:制作视频卡片。我们将使用 JS 动态创建卡片。因此,出于样式方面的考虑,我们将用 HTML 创建一个卡片。并确保为所有视频卡片创建一个容器。
<div class="video-container">
<div class="video">
<img src="img/profile-pic.png" class="thumbnail" alt="">
<div class="content">
<img src="img/profile-pic.png" class="channel-icon" alt="">
<div class="info">
<h4 class="title">youtube clone 2021 | create working youtube clone</h4>
<p class="channel-name">modern web</p>
</div>
</div>
</div>
</div>
CSS
.video-container{
width: calc(100% - 250px);
margin-top: 120px;
margin-left: 250px;
padding: 20px;
display: grid;
grid-template-columns: repeat(4, 25%);
grid-gap: 20px 5px;
overflow-x: hidden;
}
.video{
min-height: 250px;
height: auto;
}
.thumbnail{
width: 100%;
height: 150px;
object-fit: cover;
}
.content{
width: 100%;
height: 100px;
padding: 10px;
display: flex;
justify-content: space-between;
}
.channel-icon{
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
margin-right: 10px;
}
.title{
width: 100%;
height: 40px;
overflow: hidden;
}
.channel-name{
font-size: 14px;
margin: 2px 0;
color: #979797;
}
现在我们已经完成了样式设置。我们不需要 HTML 卡片结构了。所以,请对其进行注释。
<div class="video-container">
<!-- <div class="video">
<img src="img/profile-pic.png" class="thumbnail" alt="">
<div class="content">
<img src="img/profile-pic.png" class="channel-icon" alt="">
<div class="info">
<h4 class="title">youtube clone 2021 | create working youtube clone</h4>
<p class="channel-name">modern web</p>
</div>
</div>
</div> -->
</div>
现在去创建 YouTube API 密钥。观看此视频了解如何创建 YouTube API 密钥。API密钥。
获得 API 密钥后,将其存储在app.js
文件中的变量中。
let api_key = "your api key";
现在开始获取视频。我们需要 YouTube API 路由。你可以在 YouTube 文档中找到它。
并将此链接添加到JS文件中。
let api_key = "your api key";
let video_http = "https://www.googleapis.com/youtube/v3/videos?";
注意:在链接的最后添加“?”,因为我们需要给这个链接添加一些参数。
现在使用 fetch 方法fetch()
从 youtube 获取数据。
fetch(video_http + new URLSearchParams({
key: api_key,
part: 'snippet',
chart: 'mostPopular',
maxResults: 50,
regionCode: 'IN'
}))
.then(res => res.json())
.then(data => {
data.items.forEach(item => {
getChannelIcon(item);
})
})
.catch(err => console.log(err));
解释
您可以看到,我们正在从 YouTube 文档中获取的“video_http”获取数据。为了向 URL 添加参数,我们使用了new URLSearchParama(object)
。传递代码中提到的参数。它们的含义不言自明。parampart
定义了我们需要的数据类型,在本例中,我们需要所有与视频相关的数据。因此,传递snippet
。
获取数据后,我们通过 将其转换为 JSON res.json()
。您可以查看 YouTube 数据结构。 我们需要的所有数据都在 item 的数组中。因此,从循环获取 JSON 数据后,通过using方法将该 item 传递给名为 的函数。res.json()
data.items
forEach()
getChannelIcon(item)
这个函数的作用是什么?嗯,如果你查看 YouTube 视频的数据,它包含了所有内容,但没有频道图标。而我们也需要频道图标。所以我们必须单独获取图标。使用“channel_http”
并将此 HTTP 存储在我们的app.js
文件中。在我们的video_http
变量下面。
let video_http = "https://www.googleapis.com/youtube/v3/videos?";
let channel_http = "https://www.googleapis.com/youtube/v3/channels?";
然后在链接末尾添加“?”。
现在,实现该getChannelIcon
功能。
const getChannelIcon = (video_data) => {
fetch(channel_http + new URLSearchParams({
key: api_key,
part: 'snippet',
id: video_data.snippet.channelId
}))
.then(res => res.json())
.then(data => {
video_data.channelThumbnail = data.items[0].snippet.thumbnails.default.url;
makeVideoCard(video_data);
})
}
解释
在这个函数中,我们获取单个视频的数据,因为我们调用了循环,记得吗?获取单个视频的数据后,我们向 YouTube API 请求频道信息。再次使用URLSearchParam
添加参数。video_data.snippet.channelId
传入id
参数。获取响应后,通过调用 将其转换为 JSON res.json()
,并将数据转换为 JSON。设置video_data.channelThumbnail
为data.items[0].snippet.thumbnails.default.url
。
通过这种方式,我们成功地将频道图标 URL 添加到了我们的实际视频数据中。
此后,我们调用另一个函数makeVideoCard(data)
。此函数用于创建卡片。
现在,创建视频卡。但在创建此功能之前,请从 HTML 中选择我们的视频容器元素。
const videoCardContainer = document.querySelector('.video-container');
const makeVideoCard = (data) => {
videoCardContainer.innerHTML += `
<div class="video" onclick="location.href = 'https://youtube.com/watch?v=${data.id}'">
<img src="${data.snippet.thumbnails.high.url}" class="thumbnail" alt="">
<div class="content">
<img src="${data.channelThumbnail}" class="channel-icon" alt="">
<div class="info">
<h4 class="title">${data.snippet.title}</h4>
<p class="channel-name">${data.snippet.channelTitle}</p>
</div>
</div>
</div>
`;
}
解释
在这个函数中,由于我们需要将卡片附加到视频容器元素中,因此请使用innerHTML
方法在元素内添加 HTML 代码videoContainer
。记住使用+=
而不是 ,=
因为我们要添加 HTML 代码而不是重写 HTML。
好了,我们添加的内容是,我们已经有了 HTML 卡片结构。复制代码并粘贴到这里。但template string
在这里使用。这样,添加带有文本的变量就很容易了。
粘贴HTML结构后,删除实际的图像来源和标题,频道名称改为使用${variable}
它来添加变量。
video
元素内部的最后一项用于onclick="location.href = 'https://youtube.com/watch?v=${data.id}'"
添加点击事件。
我们的视频卡已经完成了。
最后一件事 - 搜索框
要使搜索框发挥作用,首先选择搜索框和搜索按钮。
const searchInput = document.querySelector('.search-bar');
const searchBtn = document.querySelector('.search-btn');
并创建一个变量来存储搜索路线。
let searchLink = "https://www.youtube.com/results?search_query=";
好吧,我从哪里得到这个链接呢?你可以在下图中看到。你可以看到,这是一个 YouTube 用来搜索视频的真实链接。我们可以用这个 URL,只需要修改一下param 的值。search_query
现在,我们拿到了链接。给按钮添加点击事件,并验证搜索框。像这样。
searchBtn.addEventListener('click', () => {
if(searchInput.value.length){
location.href = searchLink + searchInput.value;
}
})
并且在该条件内使用location.href
重定向用户。
我们完成了。
好了,就是这样。希望你理解了所有内容。如果你有疑问或者我遗漏了什么,请在评论区告诉我。
您可能觉得有用的文章
如果你喜欢,可以订阅我的YouTube频道。我创作了很棒的网页内容。订阅
感谢您的阅读。
文章来源:https://dev.to/themodernweb/create-working-youtube-clone-with-search-box-youtube-api-2a6e