凡走過必留下痕跡,時間軸年表常應用於紀錄故事和里程碑上,更是構築形象的第一步。不論是用於個人或是品牌,都能幫助網站造訪者能快速暸解關於你的歷史發展,一個常見且好用的表示方法。
我們將以Code Pen做為本次實作的平台,這是一個可以在創作的當下即時看到程式碼運作狀況的線上程式碼編輯器,只要簡單註冊就可以使用囉!
如果想搭配直播影片一起實作,請往這邊走 👉🏻 https://www.youtube.com/watch?v=Ib2YMG56_60
在開始製作年表之前我們需要準備以下步驟:
- 資料──也就是呈現在年表上的內容,舉凡文案、年份、圖片等資料,一般是儲存在資料庫內
- 版面配置──物件位置關係規劃、色票和尺寸library建置
- 插入資料──讀取資料的trigger和loading動畫
在Code Pen上開一個新的pen,將HTML的預處理器設定成Pug、CSS的預處理器設定成Sass、JS的CDN掛入Vue。

資料準備
首先來準備資料,通常年表會包含這些資料,標題、內容、年份、日期,資料儲存的形式會是每一筆都有自己的年月份,再依照日期順序做排列。命名一個陣列為logs在裡面輸入year、content等內容,在content內使用另外一個陣列再做資料渲染彈性會比較大,也可以加入不同的tag區分同年份中的不同事件。
資料的樣式可參考以下範例:
//JS
var logs = [
{
year: 2014,
content: [
{
tag: "開始接網頁專案",
},
{
tag: "開始接網頁專案2"
}
]
}]
在console裡面輸入logs,如果出現陣列代表資料準備完成。

接著我們把資料用ul列表的方式印出來,在JavaScript定義一個新的Vue並設定它的作用範圍、套用的資料為logs。在HTML的ul列表內,把logs印成一筆一筆的li,這時會看到我們原先設定的四筆資料,並且分為year、content等細部內容。
//JS
var vm = new Vue({
el: "#app",
data: {
logs: logs
}
});
//HTML
#app
ul
li(v-for="l in logs")
h3.year {{l.year}}
ul.content
li(v-for="c in l.content") {{c.tag}}

由於某些網頁的HTML標籤會帶有原生的CSS,比如剛剛使用的ul自帶圓圈和margin的樣式,我們在codepen引入reset CSS做樣式重置。
延伸閱讀:[CSS] 跨瀏覽器的樣式重置 reset.css & normalize.css
版面配置
樣式重置完後我們就可以來做設計發想啦,時間軸年表的排列比較複雜,可以參考下面的簡易草稿來構思物件之間的位置關係。我們用 dialog_wrapper 和 dialog 分別對應下圖的年份與事件,在HTML包覆相對應的資料。

//HTML
#app
ul
li.dialog_wrapper(v-for="l in logs")
.dialog
h3.year {{l.year}}
ul.content
li(v-for="c in l.content") {{c.tag}}
接下來建置色票和常用尺寸的library,本次使用的色票如下,常用到的寬高也建置 mixin 模組方便快速取用:
//CSS $color_light_blue: #D4EBE8 $color_dark_blue: #4FBDBC $color_white: white $color_yellow: #F4DF38 $color_orange: #F4A373 @mixin size($w, $h: $w) //如果寬高數值一樣,取寬 width: $w height: $h
這邊介紹大家一個好用的語法縮寫網站──Sass cheatsheet,熟練這些語法的話就可以增進切版的速度唷!
在版面設計的部分我們給背景壓上一層淡藍色,然後撐開寬高到100%。接著處理dialog的部分,可以切分為以下幾個元件:
//CSS
body
background-color: $color_light_blue
+size(100%)
.dialog
// dialog本體的樣式設定
background-color: #fff
padding: 15px 20px
cursor: pointer
border-radius: 5px
box-shadow: 15px 15px $color_dark_blue
width: 250px
position: relative
transition: 0.5s // 漸變動畫較柔和
// 裝飾性小方塊設定
&:before
content: ""
display: block
+size(20px)
border-radius: 3px
position: absolute
right: -10px
background-color: $color_white
transform: rotate(45deg)
//滑鼠移上去時,方塊往左上方、陰影往右下方移動
&:hover
transform: translate(-10px, -10px)
box-shadow: 20px 20px $color_dark_blue
// 標題文字設定
.year
font-size: 36px
font-weight: 700
margin-bottom: 10px
letter-spacing: 2px
如果對於偽元素的運用不是那麽地熟悉,可以參考這篇文章──CSS 偽元素 ( before 與 after )
接著長出 timeline 讓他在畫面中上下左右置中。根據我們上方的草稿, dialog 的位置其實是由 dialog_wrapper 的相對關係所決定的,所以給予一些高度後在 dialog_wrapper 上增加 position: relative ,在 dialog 上改為 position: absolute。
//HTML
#app
ul.timeline //加個.timeline
li.dialog_wrapper(v-for="l in logs")
.dialog
h3.year {{l.year}}
ul.content
li(v-for="c in l.content") {{c.tag}}
//CSS #app display: flex align-items: center justify-content: center .timeline height: 100vh width: 6px background-color: rgba($color_white, 0.4) padding-top: 50px .dialog_wrapper height: 160px position: relative .dialog ... position: absolute

那要如何讓 dialog 左右交錯排列呢?我們可以在 dialog_wrapper 裡面把它分為偶數和單數,用語法 :nth-child 選擇第 2n 和 2n+1 個,可以暫時設定不同的顏色有助於判別。接著調整 dialog 與 timeline 的距離,記得 left 的值會優先於 right ,所以在偶數排設定 left: initial ,再透過偽元素 &:before 調整偏右對話框的小尾巴。
//CSS
.dialog_wrapper
...
&:nth-child(2n+1)
background-color: blue
.dialog
left: 40px
&:before
left: -10px
&:nth-child(2n)
background-color: red
.dialog
right: 40px
left: initial
.dialog
...
right: 0

接著利用 dialog_wrapper 的偽元素做出時間軸上的圓圈點,我們的時間軸年表樣式大致上完成囉。
//CSS
.dialog_wrapper
height: 160px
position: relative
&:before
content: ""
display: block
+size(20px)
border: solid 5px white
border-radius: 50%
left: 50%
transform: translateX(-40%)
left: 0
top: 0px
...
插入資料
新增用來插入資料的 button ,修改初始時 logs 為空值,定義他的 methods 在 initial 時動態等於一開始所定義的 logs 。
//HTML #app button.initial(@click="initial") 插入資料 ul.timeline ...
//CSS button.initial position: fixed right: 50px bottom: 50px background-color: $color_dark_blue color: white border: none border-radius: 5px padding: 5px 10px font-size: 16px cursor: pointer
//JS
//將JavaScript兩段程式碼濃縮成為一個
var vm = new Vue({
el: "#app",
data: {
logs: []
},
methods: {
initial(){
this.logs=[];
this.logs=[
{
year: 2014,
content: [
{tag: "開始接網頁專案",
}
]
},
{
year: 2015,
content: [
{tag: "成立墨雨設計工作室",
}
]
},
{
year: 2016,
content: [
{tag: "開設動態互動網頁程式入門",
}
]
},
{
year: 2017,
content: [
{tag: "開設動態互動網頁特效入門",
}
]
}
]
}
}
});

以目前及時出現的效果來說其實有些粗糙,所以我們來加上一些loading時的動畫提升質感吧!這次使用Vue官方的效果Transition Group,使用方法為在HTML套用官方已寫好CSS效果的class就好囉,記得也要把語法在CSS複製貼上唷!這樣點「插入資料」的按鈕,就可以看到進場的動畫了。當然也可以搭配設計的CSS互動動畫,這部分就留給大家發揮空間、腦力激盪一下~
//HTML
#app
button.initial(@click="initial") 插入資料
transition-group.timeline(tag="ul",name="fade")
li.dialog_wrapper(v-for="l in logs", :key="1")
.dialog
h3.year {{l.year}}
ul.content
li(v-for="c in l.content") {{c.tag}}
//CSS ... .fade-enter-active, .fade-leave-active transition: .5s transform: translateY(0px) .fade-enter, .fade-leave-to opacity: 0 transform: translateY(50px) rotate(10deg)

至於一個一個排序進入的動畫,我們同時抓出物品跟現在是第幾個的id,用 transition-delay 加上秒數,動態指定動畫時間delay多久。
//HTML
li.dialog_wrapper(v-for="(l,id) in logs", :key="l", :style="{'transition-delay':id/2+'s'}")
最後撒上如巧克力米般的 deco_bar 妝點整個畫面,然後再加上下雨般的動畫,我們就大功告成啦。
//HTML
#app
button.initial(@click="initial") 插入資料
transition-group.timeline(tag="ul",name="fade")
li.dialog_wrapper(v-for="(l,id) in logs", :key="l", :style="{'transition-delay':id/2+'s'}")
.dialog
h3.year {{l.year}}
.decor_bar
ul.content
li(v-for="c in l.content") {{c.tag}}
//CSS
@keyframes rain_in
0%
transform: translateY(-50px)
opacity: 0
100%
transform: translateY(0px)
opacity: 1
.decor_bar
&,&:before,&:after
content: ""
+size(8px,30px)
background-color: $color_yellow
border-radius: 5px
position: absolute
top: -35px
left: 30px
animation: rain_in 0.5s 0.5s both
&:before
background-color: $color_orange
top: -30px
left: -20px
animation-duration: 1s
animation-delay: 0.5s
&:after
background-color: $color_white
top: -60px
left: 20px
animation-duration: 2s
animation-delay: 0.5s
成品請參考這邊 👉🏻 https://codepen.io/frank890417/pen/rwrZwe?editors=0010
以上就是這次可愛的時間軸年表教學,相較於其他的直播內容,這次講解到CSS相關的切版觀念,讓我們再一次複習運用到哪些重點概念。
觀念大補帖
- 物件相對、絕對位置關係──層層相疊的物件如何使用position來呼應位置
- Animation的運用──如何使用Vue transition group與撰寫CSS的keyframes
- CSS選取器──運用:nth-child等語法選取肚子裡的子層
只要熟悉這些概念,相信成為切版高手的路就不遠啦!那麼,我們下次見啦👋👋👋
動畫互動網頁程式入門(HTML/CSS/JS)以簡單例子帶你入門網站的基礎架構及開發,用素材刻出簡單有趣又美觀的網頁和動畫,享受做出獨一無二的網頁所帶來的成就感,在職場上與設計師和工程師合作無間。
打好基本的互動網頁基礎之後,可以進階動畫互動網頁特效入門(JS/CANVAS),紮實掌握JavaScript 程式與動畫基礎以及進階互動,整合應用掌控資料與顯示的Vue.js前端框架,完成具有設計感的互動網站。長達3085分鐘,超過60個精緻範例與400張的投影片以上,以及四個加碼單元vue-cli、GSAP、D3、Three.js的投影片,成為hahow上最長的課程。
此篇直播筆記由幫手 Jeudi Kuo 協助整理




