Google Slidesの一覧ページをつくる (Vue.jsとGASでタイトル・サムネイルの表示)
はじめに
ポートフォリオサイトを作っていて、今までに作成したGoogle Slidesの一覧ページをつくりたくなりました。
いわゆる「スライド共有サービス」というものもいくつかありますが、それらはスライドを画像やPDFに変換してからアップロードする必要があります。そのため、アニメーションや動画の埋め込みなどの表現は失われてしまいます。また、公開後にスライドを修正する場合には、修正の度に画像化とアップロードが必要になります。
それに対してGoogle Slidesは、Google Docsなどと同じように「ウェブに公開」することができます。「ウェブに公開」することで、以下のような共有URLが発行されます。
docs.google.com
「ウェブに公開」機能を使ってスライドの共有をすれば、スライドの表現も失われず、修正もそのまま反映されます。
今回は、このGoogle Slidesの共有URLをサムネイル付きで一覧表示するWebページを作ってみました。
要件定義
スライド一覧ページを作るにあたって、以下の要件を定義しました。
- スライドの表現(アニメーション・動画埋め込みなど)が失われない
- 公開後の修正が簡単
- 一覧ページへスライドを登録する手順が簡単
- スライドのサムネイルを表示できる
- 既存のポートフォリオサイト(Vue.js製)に埋め込める
スライドの表現が失われない・公開後の修正が簡単
これらはGoogle Slidesを使えば満たすことができます。
一覧ページへスライドを登録する手順が簡単
Google Drive上に公開用のフォルダを作り、一覧ページで公開したいスライドはそのフォルダに入れることにしました。これなら一覧ページへの登録・解除は簡単です。ここで、何らかの方法で「Google Drive上の特定のフォルダ内のスライドの情報を取得する」必要があります。これはGASで実装することにしました。やはり餅は餅屋です。
スライドのサムネイルを表示できる
GASのgetThumbnailメソッドを使います。これは、Google Drive上のファイルのサムネイルを取得するものです。
Class File | Apps Script | Google Developers
このメソッドの返り値はBlobというGAS独自のオブジェクトなので、これをbase64でエンコードしてフロントに返すようにしました。GASのBlobについては以下の記事が参考になりました。
GAS の Blob とファイル変換まとめ - Qiita
GAS側の実装
GASのコードは以下のようになります。
// HTTP GETリクエストで発火 function doGet(){ // 公開用フォルダ内のファイル情報を取得 let data = []; const files = DriveApp.getFolderById("<公開用フォルダのID>").getFiles(); while (files.hasNext()) { const file = files.next(); data.push({ "name": file.getName(), // ファイル名 "url": file.getUrl(), // 共有URL "created": file.getDateCreated(), // ファイル作成日時 "thumbnail": blob2base64(file.getThumbnail()), // サムネイル画像(base64) }); } // ファイルの作成日時が新しい順にソート data.sort(function(a, b){ if( a.created > b.created ) return -1; if( a.created < b.created ) return 1; return 0; }); // dataをjsonとして返す const json = JSON.stringify(data); const output = ContentService.createTextOutput(json); output.setMimeType(ContentService.MimeType.JSON); return output; } // blob から base64 image への変換 function blob2base64(blob) { const contentType = blob.getContentType(); const base64Data = Utilities.base64Encode(blob.getBytes()); // 単にbase64エンコーディングするだけでなく、ヘッダも必要 return "data:" + contentType + ";base64," + base64Data; }
Vue.js側の実装
Vue.jsのコードは以下のようにしました。
portfolio/Slides.vue at main · w-haibara/portfolio · GitHub
<template> <v-sheet class="blue-grey--text text--darken-4" height="100%" tile> <v-container> <h1 class="font-weight-medium">Slides</h1> <div v-if="!slidesLoaded"> <v-progress-linear indeterminate color="blue-grey darken-5" bottom ></v-progress-linear> </div> <div v-else> <v-layout wrap> <v-flex v-for="slide in slides" :key="slide.url"> <v-hover> <template v-slot="{ hover }"> <v-card :class="`elevation-${hover ? 4 : 0}`" class="transition-swing my-1" flat tile color="grey lighten-4" width="24vw" :href="slide.url" target="_blank" rel="noopener" > <v-img :src="slide.thumbnail"></v-img> <v-card-title> <span> {{ slide.name }} <v-icon color="blue-grey darken-5" x-small right> fas fa-external-link-alt </v-icon> </span> </v-card-title> <v-card-text> {{ slide.created }} </v-card-text> </v-card> </template> </v-hover> </v-flex> </v-layout> </div> </v-container> </v-sheet> </template> <script> export default { data: () => ({ slides: { id: { name: "", created: "", thumbnail: "", url: "", }, }, slidesLoaded: false, }), created() { this.axios .get( "<GASでウェブアプリケーションとして公開したURL>" ) .then((response) => { this.slides = response.data; this.slidesLoaded = true; }); }, }; </script>
おわりに
こういうときにGASは便利ですねー。