前置き
チャットアプリシリーズ第三弾❤️
CSSを整えたいところですが、
まずは画像の投稿&取得から!
前回はこちら
【Nuxt.js】開発ブログ:firebaseでチャットアプリ②
画像の投稿
投稿フォームで
選択した画像を表示・確認し、
投稿できるようにします👀
参考: SVG Background Imageの色をCSSで変える方法
input type="file"のデザイン
これ自体にCSSが効かないため、
inputは非表示にし
labelに装飾をしていきます💫
アイコンは
iconmonstrのpicture-1を使用🍒background-image
にsvg
を適応させています。svg
コードはiconmonstrコピペしてpath
の後ろにfill
を追加するだけです。
とりあえずdata:image/svg+xml
してsvg
コードつけてfill
で色つければOKです🙆♀️
1 |
background-image: url('data:image/svg+xml, <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23000" d="M5 8.5c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5c0 .829-.672 1.5-1.5 1.5s-1.5-.671-1.5-1.5zm9 .5l-2.519 4-2.481-1.96-4 5.96h14l-5-8zm8-4v14h-20v-14h20zm2-2h-24v18h24v-18z"/></svg>'); |
該当コード部分はこんな感じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
<form @submit.prevent> <label class="img" > <input type="file" class="file" > </label> // 省略(メッセージなど) <button type="submit" @click="submit" > Submit </button> </form> <style lang="scss" scoped> .page { padding: 20px; > ul { margin-top: 100px; background-color: #f8f8f8; padding: 24px 8px; > li { display: flex; margin-bottom: 10px; &.me { justify-content: flex-end; > div { background-color: pink; } } } } > form { margin-top: 20px; background-color: rgba(255, 192,203, 0.1); > label, button { display: block; // labelに装飾 &.img { width: 32px; height: 32px; background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="%23000" d="M5 8.5c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5c0 .829-.672 1.5-1.5 1.5s-1.5-.671-1.5-1.5zm9 .5l-2.519 4-2.481-1.96-4 5.96h14l-5-8zm8-4v14h-20v-14h20zm2-2h-24v18h24v-18z"/></svg>'); background-repeat: no-repeat; background-size: cover; } > input { border: 1px solid pink; // input type="file"を非表示 &.file { display: none; } } } } } </style> |
Sassでfillを変数にしようとしたが…
これが結構たいへんそうでした😩
カラーコードの#
を%23
に
エンコードする必要があるようです。
これで使えれば早いんですが、、、fill="{$color-icon}"
$color-icon: #4169e1;
ここはまた時間つくってやります🍎
参考: 多分これが一番早い SVG Background Image の利用手順だと思います
⬇️Sassの導入などは
こちらで解説しています🌟
【Nuxt.js】Sassの導入方法
選択した写真を表示する
とりあえず表示。
これを後ほどfirebaseの
storageに送信します。
⬇️まだ送信していませんが、
表示だけでもこちらの解説で
仕組みを解説していますので
ぜひご覧ください💕
主にFileReaderの確認あたりです💡
【Nuxt.js】firebase基礎編:Cloud Storageで画像アップロード&取得
選択した画像はwidth: 100px;
height: auto;
とかでとりあえず表示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
<form @submit.prevent> <label class="img" > <input type="file" class="file" // イベント追加 @change="changeImg" > </label> // 省略(メッセージなど) <button type="submit" @click="submit" > Submit </button> </form> <script> export default { data () { return { email: '', password: '', thumbnail: '', user: { email: '', name: "", message: "", }, posts: "", postData: { thumbnail: '', }, } }, methods: { changeImg (e) { this.thumbnail = e.target.files[0] if (this.thumbnail) { const reader = new FileReader() reader.onload = () => { this.postData.thumbnail = reader.result + '' } reader.readAsDataURL(this.thumbnail) } }, }, } </script> |
画像を投稿する
submit
時にstorageに
urlデータに変換したthis.thumbnail
を送信。
同時にメッセージなどと
一緒にpostData.thumbnail
を
RDBに送信📤
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
submit () { let Ref = firebase.database().ref().child('message') let stamp = firebase.database.ServerValue.TIMESTAMP Ref.push({ name: this.user.name, message: this.user.message, userId: this.user.email, time: stamp, thumbnail: this.postData.thumbnail }) .then(response => { this.getData () this.user.name = '' this.user.message = '' }) let storage = firebase.storage() let storageRef = storage.ref().child('file.png') storageRef.put(this.thumbnail) .then(res => console.log(res)) .catch(error => console.log(error)) }, |
データがぐちゃぐちゃになったので
userにまとめます…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
data () { return { email: '', password: '', thumbnail: '', user: { email: '', name: "", message: "", }, posts: "", postData: { // userにまとめる thumbnail: '', }, } }, |
ここまでのコードはこちら
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
<template> <div class="page"> <form class="form" @submit.prevent > <label class="label"> <span class="label"> email </span> <input class="input" type="text" v-model="email" > </label> <label class="label"> <span class="label"> password </span> <input class="input" type="password" v-model="password" > </label> <button class="button" type="submit" @click="login" > Login </button> </form> <ul> <li v-for="post in posts" :key="post.id" :class="{ me: user.email === post.userId}" > <div> {{ post.name }} | {{ post.message }} | {{ $dayjs(post.time).format('MM-DD HH:mm') }} </div> </li> </ul> <form @submit.prevent> <label class="img" > <input type="file" class="file" @change="changeImg" > </label> <img :src="user.thumbnail" alt=""> <label> <span> 名前: </span> <input type="text" v-model="user.name" > </label> <label> <span> message: </span> <input v-model="user.message" > </label> <button type="submit" @click="submit" > Submit </button> </form> </div> </template> <script> import axios from 'axios' import firebase from '@/plugins/firebase' export default { created() { return axios .get('https://sample-6a560.firebaseio.com/message.json') .then((res) => { const postArray = [] for (const key in res.data) { let allKey = res.data[key] postArray.push(allKey) } this.posts = postArray // console.log(this.posts) }) }, data () { return { email: '', password: '', thumbnail: '', user: { email: '', name: "", message: "", thumbnail: '', }, posts: "", } }, methods: { submit () { let Ref = firebase.database().ref().child('message') let stamp = firebase.database.ServerValue.TIMESTAMP Ref.push({ name: this.user.name, message: this.user.message, userId: this.user.email, time: stamp, thumbnail: this.user.thumbnail }) .then(response => { this.getData () this.user.name = '' this.user.message = '' }) let storage = firebase.storage() let storageRef = storage.ref().child('file.png') storageRef.put(this.thumbnail) .then(res => console.log(res)) .catch(error => console.log(error)) }, getData () { return axios .get('https://sample-6a560.firebaseio.com/message.json') .then((res) => { const postArray = [] for (const key in res.data) { let allKey = res.data[key] postArray.push(allKey) // console.log(allKey) } this.posts = postArray }) }, login() { firebase.auth().signInWithEmailAndPassword(this.email, this.password) .then(data => { console.log(data.user.email) this.user.email = data.user.email }).catch((error) => { console.log(error) }); }, changeImg (e) { this.thumbnail = e.target.files[0] if (this.thumbnail) { const reader = new FileReader() reader.onload = () => { this.user.thumbnail = reader.result + '' } reader.readAsDataURL(this.thumbnail) } }, }, } </script> <style lang="scss" scoped> .page { padding: 20px; > ul { margin-top: 100px; background-color: #f8f8f8; padding: 24px 8px; > li { display: flex; margin-bottom: 10px; &.me { justify-content: flex-end; > div { background-color: pink; } } } } > form { margin-top: 20px; background-color: rgba(255, 192,203, 0.1); > label, button { display: block; &.img { width: 32px; height: 32px; background-image: url('data:image/svg+xml, <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="{$color-font-main}" d="M5 8.5c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5c0 .829-.672 1.5-1.5 1.5s-1.5-.671-1.5-1.5zm9 .5l-2.519 4-2.481-1.96-4 5.96h14l-5-8zm8-4v14h-20v-14h20zm2-2h-24v18h24v-18z"/></svg>'); background-repeat: no-repeat; background-size: cover; } > input { border: 1px solid pink; &.file { display: none; } } } img { width: 100px; height: auto; } } } </style> |
参考: スマホアプリ開発を加速する,Firebaseを使ってみよう 第10回[最終回] Firebaseの実践的なテクニックを使いこなそう
画像の取得
こちらを追記するだけです♪<img :src="post.thumbnail" alt="">
CSSの調整は必要なものの、
かなり理想の機能が揃ってきました❤️
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
<template> <div class="page"> <form class="form" @submit.prevent > <label class="label"> <span class="label"> email </span> <input class="input" type="text" v-model="email" > </label> <label class="label"> <span class="label"> password </span> <input class="input" type="password" v-model="password" > </label> <button class="button" type="submit" @click="login" > Login </button> </form> <ul> <li v-for="post in posts" :key="post.id" :class="{ me: user.email === post.userId}" > <div> {{ post.name }} | {{ post.message }} | {{ $dayjs(post.time).format('MM-DD HH:mm') }} <img :src="post.thumbnail" alt=""> </div> </li> </ul> <form @submit.prevent> <label class="img" > <input type="file" class="file" @change="changeImg" > </label> <img :src="user.thumbnail" alt=""> <label> <span> 名前: </span> <input type="text" v-model="user.name" > </label> <label> <span> message: </span> <input v-model="user.message" > </label> <button type="submit" @click="submit" > Submit </button> </form> </div> </template> <script> import axios from 'axios' import firebase from '@/plugins/firebase' export default { created() { return axios .get('https://sample-6a560.firebaseio.com/message.json') .then((res) => { const postArray = [] for (const key in res.data) { let allKey = res.data[key] postArray.push(allKey) } this.posts = postArray console.log(this.posts) }) }, data () { return { email: '', password: '', thumbnail: '', user: { email: '', name: "", message: "", thumbnail: '', }, posts: "", } }, methods: { submit () { let Ref = firebase.database().ref().child('message') let stamp = firebase.database.ServerValue.TIMESTAMP Ref.push({ name: this.user.name, message: this.user.message, userId: this.user.email, time: stamp, thumbnail: this.user.thumbnail }) .then(response => { this.getData () this.user.name = '' this.user.message = '' }) let storage = firebase.storage() let storageRef = storage.ref().child('file.png') storageRef.put(this.thumbnail) .then(res => console.log(res)) .catch(error => console.log(error)) }, getData () { return axios .get('https://sample-6a560.firebaseio.com/message.json') .then((res) => { const postArray = [] for (const key in res.data) { let allKey = res.data[key] postArray.push(allKey) // console.log(allKey) } this.posts = postArray }) }, login() { firebase.auth().signInWithEmailAndPassword(this.email, this.password) .then(data => { console.log(data.user.email) this.user.email = data.user.email }).catch((error) => { console.log(error) }); }, changeImg (e) { this.thumbnail = e.target.files[0] if (this.thumbnail) { const reader = new FileReader() reader.onload = () => { this.user.thumbnail = reader.result + '' } reader.readAsDataURL(this.thumbnail) } }, }, } </script> <style lang="scss" scoped> .page { padding: 20px; > ul { margin-top: 100px; background-color: #f8f8f8; padding: 24px 8px; > li { display: flex; margin-bottom: 10px; &.me { justify-content: flex-end; > div { background-color: pink; } } > div { img { width: 100px; } } } } > form { margin-top: 20px; background-color: rgba(255, 192,203, 0.1); > label, button { display: block; &.img { width: 32px; height: 32px; background-image: url('data:image/svg+xml, <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="{$color-font-main}" d="M5 8.5c0-.828.672-1.5 1.5-1.5s1.5.672 1.5 1.5c0 .829-.672 1.5-1.5 1.5s-1.5-.671-1.5-1.5zm9 .5l-2.519 4-2.481-1.96-4 5.96h14l-5-8zm8-4v14h-20v-14h20zm2-2h-24v18h24v-18z"/></svg>'); background-repeat: no-repeat; background-size: cover; } > input { border: 1px solid pink; &.file { display: none; } } } img { width: 100px; height: auto; } } } </style> |
ただし今の段階では
storageにはfile.pngという名前の
1枚しか保存されていません💥
urlデータで透過、非透過の画像
2枚が取得できていますが
storageには1枚しか保存されていない
というちょっと奇妙な状態です😂笑
ということでログインした時のdata.user.email
を入れたdataのthis.user.email
にしてみました🍒
1 |
storage.ref().child(this.user.email) |
これならユーザーのメールアドレスにつき
1枚保存になりますね💡
ここから更に
変数を使って分けると尚よし…!
何が良いのか考え中です🤔💭
まとめ
storageも事前知識があるので
やりやすかったです❤️
これが1から勉強して
コードも長くなってくると
初心者なら混乱するな…
と思いました🙄
1つ1つの
基礎を把握することの
重要さが分かります…🌟
そしてもうそろそろ
VuexもCSSも
やりたいところです!😂笑
それが終わったら
データの削除をやろうかと思っております💡