iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
Vue.js

業主說給你30天學會Vue系列 第 28

V28_Vue的小專案_youtube點播機(2)

  • 分享至 

  • xImage
  •  

V28_Vue的小專案_youtube點播機(2)

在上一篇的發文中,對於小專案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>

https://ithelp.ithome.com.tw/upload/images/20231011/20152098mfbJZzBZZw.png

下一篇就會進到 隨機播放,順序播放,及上傳播放清單的功能,
這樣就算是完成小專案 youtube點播機 的功能了

最後補充一下
在網址後面加上 "?autoplay=1" 就可以自動播放了
ytlink = "https://www.youtube.com/embed/"+this.videoID+"?autoplay=1"


上一篇
V27_Vue的小專案_youtube點播機(1)
下一篇
V29_Vue的小專案_youtube點播機(3)
系列文
業主說給你30天學會Vue31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言