在上一篇我們製作了可以新增、拖曳、換顏色的簡易版本便利貼,這次除了調整細節與動畫外,也會串接Firebase資料庫,讓便利貼牆可以多人同時編輯與更新。
這次的教學將有以下幾個重點,主要聚焦在既有功能的優化與新功能的添加:
- 點擊便利貼文字時因滑鼠與左上角距離設定的關係,會造成距離差而產生的跳動
- 加入刪除便利貼的功能
- 加入新增或刪除便利貼時,放大縮小的transition
- 修改顏色的控制列需和正在使用中的便利貼位置相對應(上次我們處理的方式是都先暫時放在畫面右手邊,這次把它修改得人性化一些)
- 編輯文字和多行文字時呈現的大小
- 串接Firebase保存資料,即時整理與更新
我們將以Code Pen做為本次實作的平台,這是一個可以在創作的同時即時看到程式碼運作狀況的線上程式碼編輯器,只要簡單註冊就可以使用囉!
如果想搭配直播影片一起實作,請往這邊走
修正點擊便利貼文字造成的距離差
首先fork一份上一次的檔案,fork就像是複製,這樣接續修改也不會動到最初的原始檔唷。
接下來我們在CSS的.postit
裡面加上.text
下 pointer-events: none
,讓他停止觸發任何的點選事件,在製作滿版圖面但不希望阻礙滑鼠事件時,可以使用這種處理方式(比如:市面網站常見透過hamburger選單收合的滿版menu)。
加入刪除便利貼功能
刪除的概念可以想成「從包著便利貼id的陣列中,運用語法 splice() 切掉該張便利貼的id」。在colorList
中新增刪除按鈕如下:
button.btn(@click="postits.splice(pid,1)") 刪除
新增 / 刪除的transition
接著加入新增和刪除的動畫,我們使用vue的transition group處理。在使用上有以下幾點特性:
- 在HTML新增,
transition-group(name="fade"
),注意transition Group需要包成一個div使用,這邊用tag="ul"
處理,而便利貼為li
- Group內的每個物件都需要名字,才知道控制動畫的元件範圍,給他
:key="pid"
,每張便利貼都有個獨一無二的id
利用vue官方提供的效果fade
稍微調整一下語法,加入scale
讓便利貼有從小變大、長出來的效果。
//HTML #app transition-group(name="fade", tag="ul") li.postit(v-for="(p,pid) in postits", //為每張便利貼加上一個id :key="pid", :style="postitCss(p)", @mousedown="selectId($event,pid)") .text {{p.text}}
//CSS .fade-enter-active, .fade-leave-active transition: .5s .fade-enter, .fade-leave-to opacity: 0 transform: scale(0.1)
調整顏色控制列的位置
為了讓修改顏色的功能更人性化一些,我們把.colorList
整包移到.postit
裡面,用position: absolute
定位在便利貼下方。這時你會發現熟悉的點擊距離差問題又回來了,但因爲修改顏色和刪除的機制也是透過滑鼠,所以無法使用之前的方法來解決。
先前拖曳功能的設定為——點擊便利貼時,將該張便利貼設定id為0,當滑鼠移動時同步更新設定。現在把控制列跟便利貼拆成不同部分,也就是說點擊控制列時不進行id的設定。
在selectId
的event中判斷source element是否含有block
和btn
,如果沒有,則進行id的設定,如果有,則nowId=-1
:
//CSS .colorList position: absolute bottom: -80px display: flex flex-direction: row .block margin-right: 10px
//JavaScript selectId(evt,id){ console.log(evt) let isBlock = evt.srcElement.classList.contains('block') let isBtn = evt.srcElement.classList.contains('btn') if (!isBlock && !isBtn ){ this.nowId=id //滑鼠點下去 this.startMousePos = { x: evt.offsetX, y: evt.offsetY } }else{ this.nowId=-1 } }
文字編輯和多行文字時呈現的大小
如同調整顏色的控制列,我們希望在編輯文字部分可以有更好的使用者體驗,透過點擊該張便利的「編輯」按鈕即可修改。在Vue裡增加 setText 這個方法,利用語法 prompt() 跳出修改視窗,並在input欄位顯示原始的文字(透過抓取pid知道是哪張便利貼、上面有甚麼文字):
//HTML //新增編輯按鈕 button.btn(@click="setText(pid)") 編輯
//JavaScript methods:{ ... setText(pid){ //彈出視窗修改文字 let text = prompt("請輸入新的文字", this.postits[pid].text) //送出之後再便利貼上更新文字 if (text){ this.postits[pid].text=text } } }
連接Firebase資料庫
接下來進入今天的重頭戲——串接Firebase資料庫。Firebase是Google提供的雲端開發平台,協助 開發者在雲端快速建置後端服務,提供即時資料庫。這種noSQL(非關聯式)類型的資料後端平台可能是未來的趨勢,noSQL代表你不會用像select all member這種特殊的資料查詢語法,他就是一張樹狀圖,把所有東西塞進去,所以你可以看到便利貼在頁面上即時地移動與資料修改,在Firebase資料庫裡也可以看到頁面上的改動。
首先前往Firebase的控制台,新增一個for便利貼的專案。
接著選擇Realtime Database,在專案中新增child如下:
tips: 右邊的值必須要先輸入一個default數值,之後有資料存入時便會被取代掉了。
接著引入我們的codepen網頁,在codepen引進CDN,再初始化資料庫。
Step 1:進到Overview,點選「網頁」。
Step 2:將Firebase新增至codepen。CDN為第一個script內的src,初始化config為下方的firebaseConfig。
Step 3:引入CDN,第一個script內的src貼入codepen settings。
Step 4:初始化資料庫,將Step 2裡面第二個script中的程式碼複製貼在我們JS程式碼的最上方。
接著透過Firebase手動新增一張便利貼如下,注意資料的層級,尤其是代表便利貼位置的x, y
是在pos
下面。
再把codepen跟建立好的firebase資料庫串接,並監聽他的value做即時更新,可以看到我們剛剛手動在資料庫新增的便利貼。Firebase語法可參考官方文件。
//JavaScript var postitsRef = firebase.database().ref("postits2"); //建立連結 postitsRef.on('value', (snapshot)=>{ vm.postits = snapshot.val() //即時更新 })
註:firebase串接語法已更新成firebase.database().ref(),直播內容的firebase.database.ref()為舊版。
遠端新增 / 刪除便利貼
可以透過資料庫新增並呈現在頁面上後,我們這邊試試透過codepen push便利貼進去資料庫,修改methods addPostits
的地方,讓他不是新增在vm
這邊而是postitsRef
。
//JavaScript addPostits(){ postitsRef.push( { text: "文字", color: "yellow", pos: {x: 200+Math.random()*100, y: 200+Math.random()*100 } }
我們希望能刪除特定便利貼的節點,也就是postitsRef
下的子結點,記得也需修改HTML刪除按鈕的語法為@click="deletePostit(pid)"
,並在JS新增以下methods:
deletePostit(pid){ postitsRef.child(pid).remove(); }
同步顏色 / 文字 / 拖移位置
除了更新頁面上便利貼的位置,也同步更新遠端資料庫的位置,所以在mousePos
抓這張便利貼this.nowId
,設定set
更新遠端資料庫的值。
//JavaScript postitsRef.child(this.nowId).set(this.postits[this.nowId])
同步文字的邏輯也是類似的,在setText
做完本地更新後,也一起更改資料庫的文字。
//JavaScript postitsRef.child(pid).set(this.postits[pid])
最後一個則是顏色,我們原先是讓便利貼的顏色等於顏色的名字p.color=color.name
,現在為了更新遠端資料 ,我們把它包成一個function叫setColor
。在methods定義setColor
的作用,概念和setText
類似。
//HTML .colorList .block(v-for="color in colorList", :style="{backgroundColor: color.color}", //修改成成為setColor function @click="setColor(pid, color.name)")
//JavaScript setColor(pid,colorname){ this.postits[pid].color=colorname postitsRef.child(pid).set(this.postits[pid]) },
以上就是這次的直播內容,主要聚焦於功能的優化與資料庫的串接,後面firebase的部分對於初次接觸的人可能會需要一段時間的摸索,但只要成功串接起來、再多研究一下文件,就會比較好入手。
步驟總結
這次的直播內容比較複雜,所以在最後來個總重點整理一下。在上篇我們先建立便利貼的基礎,從樣式雛形到基本資料處理,可以分為以下幾個重點:
1. 便利貼樣式與資料處理 – 建立便利貼架構,色票、文字樣式和文字位置
2. 加上滑鼠互動事件 – 紀錄滑鼠移動的位置並儲存在evt,運用nowId判斷滑鼠在哪一張便利貼的範圍裡面
3. 新增便利貼與修改顏色 – 做一個button點擊觸發function addPostits,在addPostits推入新的陣列
下篇的部分我們著重在既有功能的微調、更精緻化,還有資料庫的串接:
1. 修正點擊便利貼文字造成的距離差 – pointer-events: none停止觸發任何的點選事件
2. 刪除便利貼功能 – 運用語法splice()切掉該張便利貼的id
3. 新增 / 刪除的transition – 使用vue的原生transition group處理,transition-group(name=”fade”)
4. 調整顏色控制列的位置 – 把colorList整包移postit裡面,用position: absolute定位在便利貼下方
5. 文字編輯和多行文字時呈現的大小 – 利用語法prompt()跳出修改視窗,優化文字編輯的使用者體驗
6. 連接Firebase資料庫 – 在Firebase建立專案與Realtime Database,與Codepen資料連接
7. 同步顏色 / 文字 / 拖移位置 – 在mousePos抓特定便利貼this.nowId,設定set更新遠端資料庫的值
課程推薦
動畫互動網頁程式入門(HTML/CSS/JS)以簡單例子帶你入門網站的基礎架構及開發,用素材刻出簡單有趣又美觀的網頁和動畫,享受做出獨一無二的網頁所帶來的成就感,在職場上與設計師和工程師合作無間。
打好基本的互動網頁基礎之後,可以進階動畫互動網頁特效入門(JS/CANVAS),紮實掌握JavaScript 程式與動畫基礎以及進階互動,整合應用掌控資料與顯示的Vue.js前端框架,完成具有設計感的互動網站。
那我們下次再見啦👋👋👋
此篇直播筆記由幫手 Jeudi Kuo 協助整理