在上一篇的發文中,對於小專案youtube點播機
己完成了播放機的本體
根據小專案的功能項目
1.可以解析youtube的網址來取得videoID
2.可以儲存播放清單
3.可以建立不同的播放集
4.可以隨機播放
5.可以下載播放清單
接下來要處理 儲存播放清單及播放集的部份
首先,要建立一個儲存YT影片的videoID的陣列
YT影片需要記錄的項目有 videoID, videoTitle, albumName
預計的陣列內容
let ytlist = [
{ videoID: "Ptk_1Dc2iPY", videoTitle: "Canon in D - Cello & Piano", albumName: "Canon"},
{ videoID: "7051Y4WVFJA", videoTitle: "2 Hours Of Canon in D by Pachelbel", albumName: "Canon"}
]
接著增加 videoID, videoTitle, albumName 輸入欄位 以及對應的綁定變數
vt_url -> change_yt() -> videoID -> ytlink -> <iframe :src="ytlink">
vt_album -> videoTitle
vt_album -> albumName
還有操作的功能
新增(@click="change_yt")
修改(@click="record_yt")
刪除(@click="delete_yt")
下載清單(@click="save_yt")
另外 {{ videoID }}
來顯示 videoID
3個 <input>
的 @click
都是將欄位清空
videoID, videoTitle, albumName -> ytlist
再來是列示的部份,使用<tr v-for="x in ytlist">
以及<td @click="edit_yt(x)" style="cursor:pointer">{{ x.videoID }}</td><td>{{ x.videoTitle }}</td><td>{{ x.albumName }}</td>
本身 VideoID 的 <td @click="edit_yt(x)">
是在click時,經 edit_yt(x) 將該筆資料 傳回 videoID, videoTitle, albumName 的輸入欄位上
videoID -> videoID
videoTitle -> vt_album
albumName -> vt_album
有了以上的準備,最後<template>
的程式碼整合如下
<template>
<div>
<h3>Vue YouTube Player</h3>
<h4>videoID: {{ videoID }}</h4>
Input Youtube Album: <input class="w3-input w3-border w3-round" type="text" v-model="vt_album" @click="vt_album=''">
Input Youtube Title: <input class="w3-input w3-border w3-round" type="text" v-model="vt_title" @click="vt_title=''">
Input Youtube URL: <input class="w3-input w3-border w3-round" type="text" v-model="vt_url" @click="vt_url=''">
<button class="w3-btn w3-border w3-round-large" @click="change_yt">新增</button>
<button class="w3-btn w3-border w3-round-large" @click="record_yt">修改</button>
<button class="w3-btn w3-border w3-round-large" @click="delete_yt">刪除</button>
<button class="w3-btn w3-border w3-round-large" @click="save_yt">下載清單</button>
</div>
<div>
<iframe width="640" height="360" :src="ytlink" title="" frameborder="1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
<table class="w3-table-all">
<tr><th>videoID</th><th>Video_Title</th><th>Album_Title</th></tr>
<tr v-for="x in ytlist">
<td @click="edit_yt(x)" style="cursor:pointer">{{ x.videoID }}</td><td>{{ x.videoTitle }}</td><td>{{ x.albumName }}</td>
</tr>
</table>
</template>
另外樣式的部份,引入了 w3.css
在儲存清單的部份,引入了 p5.js 的 saveJSON 的功能
所以在index.html引入2個外掛
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.js"></script>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
再來是script程式碼的部份
變數宣告的部份
data() {
return {
vt_url: "",
vt_album: "",
vt_title: "",
videoID: "",
ytlink: "",
ytlist: [
{ videoID: "Ptk_1Dc2iPY", videoTitle: "Canon in D - Cello & Piano", albumName: "Canon"},
{ videoID: "7051Y4WVFJA", videoTitle: "2 Hours Of Canon in D by Pachelbel", albumName: "Canon"}
]
};
},
新增 change_yt()
的部份
change_yt() {
let str = this.vt_url;
let urlParams = new URLSearchParams(str.split("?")[1])
let vid = urlParams.get("v");
if(vid!=null){
this.videoID = vid;
} else {
let f1 = str.indexOf("?");
if(f1!=-1){
str = str.split("?")[0];
}
let f2 = str.indexOf("youtu.be");
let f3 = str.indexOf("embed");
if(f2!=-1){
this.videoID = str.split("youtu.be/")[1];
} else if(f3!=-1){
this.videoID = str.split("embed/")[1];
} else if(str.length==11){
this.videoID = str;
} else {
this.videoID = "";
}
}
this.ytlink = "https://www.youtube.com/embed/"+this.videoID
let yt_index = this.ytlist.findIndex((e) => e.videoID === this.videoID )
if(yt_index == -1 && this.videoID.length==11){
this.ytlist.push({videoID: this.videoID, videoTitle: this.vt_title, albumName: this.vt_album})
}
console.log(this.ytlist)
},
除了上一篇有提到的之外, 還增加了,在YT網址直接輸入videoID時,也可以當作取得videoID的方式
除了輸入的videoID本身是錯誤的,有可能會讀進來,不過還是可以刪除錯誤的videoID
另外,當新輸入的videoID, 沒有在清單 ytlist,同時字串長度是 11時
就會將該筆資料加入 清單 ytlist中
檢查輸入的videoID是否有在清單 ytlist中的程式碼為let yt_index = this.ytlist.findIndex((e) => e.videoID === this.videoID )
若有找到,則yt_index是出現的索引值,若沒有找到,則yt_index是 -1
加入 清單 ytlist 的程式碼 為this.ytlist.push({videoID: this.videoID, videoTitle: this.vt_title, albumName: this.vt_album})
接著是 修改 change_yt()
的部份
edit_yt(n){
console.log(n)
this.videoID = n.videoID
this.vt_title = n.videoTitle
this.vt_album = n.albumName
this.ytlink = "https://www.youtube.com/embed/"+this.videoID
},
這個要與
<tr v-for="x in ytlist">
<td @click="edit_yt(x)" style="cursor:pointer">{{ x.videoID }}</td><td>{{ x.videoTitle }}</td><td>{{ x.albumName }}</td>
</tr>
@click="edit_yt(x)"
中的 x 是指清單中的每一個 影片資料
傳入函式後 分別將 x 的參數傳回輸入欄位
再來是 刪除 delete_yt()
的部份
delete_yt(){
let yt_index = this.ytlist.findIndex((e) => e.videoID === this.videoID )
if(yt_index != -1){
this.ytlist.splice(yt_index, 1);
}
}
先檢查 目前的 videoID 是否有在 清單ytlist中
若yt_index不是-1, 則利用this.ytlist.splice(yt_index, 1);
刪出該筆資料
是指從 該筆在清單的索引值
處,刪除一筆
最後是 下載清單 save_yt()
的部份
save_yt(){
console.log(top)
top.saveJSON(JSON.parse(JSON.stringify(this.ytlist)), 'youtube_list');
},
這裡使用到p5.js套件中 saveJSON()
的功能,
還在想要如何引到 vue當中的方法時
發現在 index.html
加入
<script>
function setup(){
noCanvas();
noLoop();
}
</script>
在top的window物件中,就會多出p5.js的功能了
其中 top.saveJSON()
就可以呼叫的到了
或許還有更正確的引入的方法
不過先這樣用了
JSON.parse(JSON.stringify(this.ytlist))
是將 this.ytlist
先轉成序列字串,再轉換成JSON格式
第2個參數 是預設儲存的檔名
最後儲存成 youtube_list.json
以上就完成播放清單的CRUD的操作了
以下是完整的程式碼
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.2/p5.js"></script>
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<title>Vue Youtube Player</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
<script>
function setup(){
noCanvas();
noLoop();
}
</script>
</body>
</html>
App.vue
<template>
<div>
<h3>Vue YouTube Player</h3>
<h4>videoID: {{ videoID }}</h4>
Input Youtube Album: <input class="w3-input w3-border w3-round" type="text" v-model="vt_album" @click="vt_album=''">
Input Youtube Title: <input class="w3-input w3-border w3-round" type="text" v-model="vt_title" @click="vt_title=''">
Input Youtube URL: <input class="w3-input w3-border w3-round" type="text" v-model="vt_url" @click="vt_url=''">
<button class="w3-btn w3-border w3-round-large" @click="change_yt">新增</button>
<button class="w3-btn w3-border w3-round-large" @click="record_yt">修改</button>
<button class="w3-btn w3-border w3-round-large" @click="delete_yt">刪除</button>
<button class="w3-btn w3-border w3-round-large" @click="save_yt">下載清單</button>
</div>
<div>
<iframe width="640" height="360" :src="ytlink" title="" frameborder="1" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
<table class="w3-table-all">
<tr><th>videoID</th><th>Video_Title</th><th>Album_Title</th></tr>
<tr v-for="x in ytlist">
<td @click="edit_yt(x)" style="cursor:pointer">{{ x.videoID }}</td><td>{{ x.videoTitle }}</td><td>{{ x.albumName }}</td>
</tr>
</table>
</template>
<script>
export default {
data() {
return {
vt_url: "",
vt_album: "",
vt_title: "",
videoID: "",
ytlink: "",
ytlist: [
{ videoID: "Ptk_1Dc2iPY", videoTitle: "Canon in D - Cello & Piano", albumName: "Canon"},
{ videoID: "7051Y4WVFJA", videoTitle: "2 Hours Of Canon in D by Pachelbel", albumName: "Canon"}
]
};
},
methods: {
change_yt() {
let str = this.vt_url;
let urlParams = new URLSearchParams(str.split("?")[1])
let vid = urlParams.get("v");
if(vid!=null){
this.videoID = vid;
} else {
let f1 = str.indexOf("?");
if(f1!=-1){
str = str.split("?")[0];
}
let f2 = str.indexOf("youtu.be");
let f3 = str.indexOf("embed");
if(f2!=-1){
this.videoID = str.split("youtu.be/")[1];
} else if(f3!=-1){
this.videoID = str.split("embed/")[1];
} else if(str.length==11){
this.videoID = str;
} else {
this.videoID = "";
}
}
this.ytlink = "https://www.youtube.com/embed/"+this.videoID
let yt_index = this.ytlist.findIndex((e) => e.videoID === this.videoID )
if(yt_index == -1 && this.videoID.length==11){
this.ytlist.push({videoID: this.videoID, videoTitle: this.vt_title, albumName: this.vt_album})
}
console.log(this.ytlist)
},
record_yt() {
let yt1 = this.ytlist.find((e) => e.videoID === this.videoID )
yt1.albumName = this.vt_album;
yt1.videoTitle = this.vt_title;
},
/**
* @param {{ videoID: string; videoTitle: string; albumName: string; }} n
*/
edit_yt(n){
console.log(n)
this.videoID = n.videoID
this.vt_title = n.videoTitle
this.vt_album = n.albumName
this.ytlink = "https://www.youtube.com/embed/"+this.videoID
},
save_yt(){
console.log(top)
top.saveJSON(JSON.parse(JSON.stringify(this.ytlist)), 'youtube_list');
},
delete_yt(){
let yt_index = this.ytlist.findIndex((e) => e.videoID === this.videoID )
if(yt_index != -1){
this.ytlist.splice(yt_index, 1);
}
}
}
}
</script>
<style>
div {
padding:10px
}
</style>
下一篇就會進到 隨機播放,順序播放,及上傳播放清單的功能,
這樣就算是完成小專案 youtube點播機 的功能了
最後補充一下
在網址後面加上 "?autoplay=1"
就可以自動播放了
ytlink = "https://www.youtube.com/embed/"+this.videoID+"?autoplay=1"