Firebaseで運用している買い物リストですが、似たような商品がいろいろある中でわかりにくい、という問題がありました。
そこで、リストに写真を追加できるようにしました。
夫婦で共有できる買い物リストを作りました。
— プログラミング素人 (@s51517765) 2020年5月2日
FirebaseのリアルタイムデータベースとStorageを利用しています。
・欲しいものを追加する
・欲しいものに写真を添付する
・入手済みリストを保持する
・スマホ(Android / iOS)から利用可能 pic.twitter.com/uPXvyGiu9f
TL;DR
・データの構造を変更・画像の保存先はFirestorageを使用
・画像があるときはアップロードした時刻よりファイル名を作成しFirestorageにアップロードする。同時にデータ構造にイメージファイル名をPush。
・リストの読み込み時は、イメージファイル名があるときは、イメージのリンクを作成。
以下、技術的な解説をします。
↓の記事で作ったFirebaseプロジェクトがベースです。
s51517765.hatenadiary.jp
画像のプレビュー
btnFileUpload
に、ボタンクリックイベントを登録します。window.onload
でページ読み込み時に登録されます。
window.onload = function () { document.getElementById('btnFileUpload').addEventListener('change', handleFileSelect, false); }
ボタンクリックで画像表示領域imgPreviewArea
をformUpload
に作成します。
var element = document.createElement("div"); element.id = "imgPreviewArea"; formUpload.append(element);
画像の大きさはCSSで設定しています。
画像表示部コードの全体
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" type="text/css" href="css.css"> <title>Document</title> </head> <body> <div> <form name="formUpload"> <input type="file" id="btnFileUpload" name="files[]"> <output id="list"></output> </form> </div> </body> <script> function handleFileSelect(evt) { var element = document.createElement("div"); element.id = "imgPreviewArea"; formUpload.append(element); //https://www.html5rocks.com/ja/tutorials/file/dndfiles/ imgFile = evt.target.files[0]; // File object if (!imgFile.type.match('image.*')) return; var reader = new FileReader(); // Closure to capture the file information. reader.onload = (function (theFile) { return function (e) { // Render thumbnail. imgPreviewArea.innerHTML = ['<img class="thumb" src="', e.target.result, '" title="', escape(theFile.name), '"/>'].join(''); }; })(imgFile); // Read in the image file as a data URL. reader.readAsDataURL(imgFile); } window.onload = function () { document.getElementById('btnFileUpload').addEventListener('change', handleFileSelect, false); }; </script> </html>
ボタンクリックで画像をアップロード
画像が読み込まれていたら、アップロードする画像があると判断して、imgUpload()
を呼び出します。
function addData() { if (imgID != "NoImage") imgUpload(); } //ストレージのルートのリファレンスを取得 var storageRef = firebase.storage().ref(); var imgUpload = function (ev) { //ストレージへアップロードするファイルのパスを生成する var uploadRef = storageRef.child(imgID); uploadRef.put(imgFile); };
リストの読み込み時に画像も読み込む
データベースのキーを拡張して、imgID
が存在すれば画像を読み込みます。従来のデータベースにはイメージのキーが無かったので、その辺も考慮して破壊的変更にならないようにしています。
これを入れないと、従来のデータが読み込めなくなります。
if (childData.imgID != undefined && childData.imgID != "" && childData.imgID != "NoImage") { ImgURL(childData.imgID, element, childData.message, cb); }
リストを読み込むときに画像も読み込みます。
画像はリストからIDを取り出し、ストレージ中の画像を指すURLを取得します。
function ListLoad() { var childData = childSnapshot.val(); var element = document.createElement("li"); subject.push(childData.message); //リストの中身を配列に追加し保持、重複確認のため //チェックボックスの追加 var cb = document.createElement("input");//チェックを作成 cb.type = "checkbox"; cb.name = "cb" cb.value = childData.message; if (childData.imgID != undefined && childData.imgID != "" && childData.imgID != "NoImage") { ImgURL(childData.imgID, element, childData.message, cb); } else { element.innerHTML = childData.message; element.appendChild(cb); } list1.append(element); } function ImgURL(imgID, element, message, cb) { if (imgID == "NoImage") return; imgSample = storageRef.child(imgID); //thenで戻り値がfunctionの引数に入る imgSample.getDownloadURL().then(function (url) { console.log(url); element.innerHTML = message + " <a href =" + url + ">image</a>"; element.appendChild(cb); }); }
まとめ
買い物リストに画像を添付できるようにしました。ちなみに、画像の削除は実装していないのでリストから削除されてもストレージには残ったままです。
管理画面から削除するという運用をしています。
github.com