LiveTRA 火車時刻表 UI 設計

LiveTRA 是我的一個 side project,開始的契機是某個時期,因時常搭乘台鐵通勤,而台鐵又經常誤點,想說如果可以在出門前就可以先得知月台上的誤點時間,就可以避免匆匆忙忙趕到車站後才發現原來列車誤點的窘況。

Google了一下馬上就找到了當時由交通部主催的「公共運輸整合資訊流通服務平台 (PTX)」API服務(目前已整合進 「運輸資料流通服務 (TDX)」),很快地就做出了第一版,以下是當時第一版的畫面設計。

舊版車站頁
舊版列車頁

舊版的頁面結構中沒有首頁,以台北車站做為預設車站當作首頁。一旦選擇過車站後,便以上一次選擇的車站當作預設顯示車站。且因為想把車站選擇器順便當作標題使用,因此將車站選擇器放在頁面最上面。

當這個版本運行一陣子後,意外地還蠻多人用的,並且收到了一些反饋,同時也因為想優化整個網站的架構,因此做了改版。

新版首頁與車站頁設計

首頁
車站頁

這個版本出現了首頁,首頁會顯示最後兩次選擇的車站的最近一班列車,以及一些子功能的入口。例如:語系選擇、誤點班次列表、列車誤點賠償規則、最近使用車站、熱門車站⋯等等。

閱讀全文 LiveTRA 火車時刻表 UI 設計

關於 vite 與 webpack 的檔案分割

之前一直很好奇 nuxt 是怎麼做到分割檔案的,但一直沒有時間來好好研究。上網搜尋一下之後,得知原來就跟寫 vue-router 想要 lazy load 的時候一樣,只要不用 import xxx from 'xxx' 匯入,而是改用 import('xxx') 的方式匯入,就會被自動分割,達成在需要的時候才 import 的目的,也就是 component 的 lazy loading。

例如當我們在 vue3 裡要宣告一個 component 的時候可以用:const xxx = defineAsyncComponent(() => import('xxx'))

以下的描述是單純以 vite or webpack 來打包程式碼的情況,而非 nuxt。

因此這個 import() 就是關鍵之處。平常較為人知的 import 是只能在一個檔案的最上頭,並且是以 import xxx from 'xxx' 這樣的形式使用。不過以這種方式 import 的話,全部的 code 將都會被打包在一起,output 到你設定的路徑。

import() 與檔案開頭使用的 import 是不同東西,不要混淆了。他是以 function 的形式來使用。且會回傳一個 Promise,當我們 const test = await import('xxx') 後,test 被賦予的是一個 Module 物件,其中會有 default 或是我們 export 的其他內容。

當我們的程式碼以 import() 來載入一個 module 時,就會使 webpack or vite 依照 import('xxx') 的檔案路徑來分割檔案,並改寫檔名(例如 Comp1-sdfkjsdpg.js),與原本 import('Comp1.js') 中的檔名(例如 import('Comp1-sdfkjsdpg.js'))。

我們也可以透過一樣的 code 來比較 vite and webpack 所分割出來的檔案。結果 vite 產生的檔案大小小很多,因為 vite 預設不會管 ESM 相容性的問題,而 webpack 則會加入許多 module 相容性的 code 在其中。

另外,我們知道由 import 載入的內容一旦被修改,別處也有 import 相同內容的地方也會拿到被修改後的資料。這個部分 import() 也是相同的。

此外我還做了一個無聊的測試,就是當網頁上有兩個 script 標籤中都 import 相同檔案時,是否結果也是一樣呢?答案是一樣!當其中一個 script 標籤中 import 的內容修改過後,另一個 script 標籤內 import 的內容也會是被修改過的(因為他們就是同一個內容)。

[歌詞翻譯] 満ちてゆく – 藤井風

這應該是藤井風繼「帰ろう」之後,另一首描繪生死的歌。非常喜歡前奏那段簡單的鋼琴旋律,以三個漸漸上升的大調和弦營造出幸福感,接續到兩個小調和弦創造出一些低迷的感覺,再回到大調與和maj7和弦,就像人生的路上時而幸福時而辛苦。在兩段重複的旋律的最後都出現了一個轉調的和弦,就像是人生中的轉折或疑問一般。這段前奏在第二次進入主歌前也再度出現了,總結了第一段對人生的反思。當進入第二段主歌時,出現了節奏樂器,打破了原有的低迷感。而整首歌在 Bridege 結束後做了轉調,讓整個氛圍突然出現豁然開朗、對人生有所頓悟的感覺。而在歌曲的最後,一樣又再重複了一次前奏的旋律,且最後停留在跟前奏最後一樣的轉調的部分,似乎象徵著關於人的生命,還有很多問題尚待自己去摸索,去尋求解答。

—— 翻譯開始 ——

走り出した午後も
重ね合う日々も
避けがたく全て終わりが来る

無論是忙碌的午後
還是我們一起度過的每一天
這些全都難以避免地會迎來結束

閱讀全文 [歌詞翻譯] 満ちてゆく – 藤井風

[日文翻譯] 辦公室的怒氣小murmur

之前幫你收爛攤子,卻被你拿去跟主管邀功,那股怒氣就在剛剛看到你被主管罵哭的時候,消失地無影無蹤。

こないだ君の仕事の尻拭いをしたら、それを自分の手柄のように上司にアピールしたよね。その怒りは、さっき君が上司に叱られて泣いているのを見た時にすっきり消えたよ。

單字解釋:
尻拭い しりぬぐい  擦屁股、收爛攤子
手柄 てがら  功勞

明明都已經不是我主管了,還在那邊指使我做東做西,怎麼這麼不要臉!

もう上司じゃないのに、あれこれ命令してくるなんて厚顔無恥にも程がある!

單字解釋:
厚顔無恥 こうがんむち  
~にも程がある  ~也要有個限度

閱讀全文 [日文翻譯] 辦公室的怒氣小murmur

[單字筆記] Web工程師相關日文單字

因爲本身是Web前端工程師,常常在查找文件或技術文章時,如果中文英文找不到需要的資訊時,也會試試看用日文來找。這時候就會接觸到一些與程式相關的日文單字,以下整理了一些實用且常看到的單字,之後如果有新增也會在這篇更新。

閱讀全文 [單字筆記] Web工程師相關日文單字

[歌詞翻譯] 雪の華 – 中島美嘉

のびたかげを舗道(ほど)にならべ
夕闇のなかを君と歩いてる
手をつないで いつまでもずっと
そばにいれたなら 泣けちゃうくらい

拉長的影子映在人行道磚上(ならべる原本是「排列」的意思,但在此翻成「映」較好懂
與你走在傍晚時分
牽著你的手,若能夠在你身邊直到永遠的話(上一句後半的「いつまでもずっと」應該是接著「そばにいれたなら」翻譯比較正確)
(這種幸福)能讓我感動地流淚

閱讀全文 [歌詞翻譯] 雪の華 – 中島美嘉

[歌詞翻譯] 僕が死のうと思ったのは – 中島美嘉

其實我對中島美嘉的歌並不熟,不過幾年前無意間看到了下面這個影片,於是就被她這麼強烈的演繹方式吸引,馬上收入歌單中!

非常喜歡這首歌的編排與設計。主歌與副歌都用同一句話做開頭,但在銜接時透過不同的旋律與轉Key來處理,不僅能建構出層次感,也帶出了一個曾經想一了百了的人,不斷在深陷泥沼與得到救贖中來來回回的實感。

前兩段主歌以冷漠的唱腔詮釋負面又消極的歌詞,副歌則是以堅定的聲音傳達理性的原委或理由。在Live版中,第一段主歌接副歌之間的接近嘶吼的吶喊橋段後,又可以立刻轉換成穩定柔和的聲線,實在非常佩服中島美嘉的唱功。最後一段的唱腔也著實讓人看見了希望般地豁然開朗。

讚讚的演唱會版
The First Take 版本

僕が死のうと思ったのは ウミネコが桟橋(さんばし)で鳴いたから
波の随意(まにま)に浮かんで消える 過去も啄(つい)ばんで飛んでいけ
僕が死のうと思ったのは 誕生日に杏(あんず)の花が咲いたから
その木漏れ日(こもれび)でうたた寝したら 虫の死骸(しがい)と土になれるかな

我也曾想過一了百了,因為黑尾鷗(一種中體型的海鷗)在棧橋上鳴叫著
隨著坡浪載浮載沉,也把過往叼著然後飛走吧
我也曾想過一了百了,因為在生日的那天杏花盛開了(杏花的花語:懷疑、疑惑
在樹葉間灑下來的陽光中小憩的話,不知能否跟蟲子的屍體一起變成塵土呢

閱讀全文 [歌詞翻譯] 僕が死のうと思ったのは – 中島美嘉

把人聲與樂器分離的超強軟體 Ultimate Vocal Remover

之前介紹過 Spleeter 這個分離人聲的軟體,不過在 M2 晶片的 Mac 上跑的時候,總是會遇到許多問題,例如顯示「illegal hardware instruction」錯誤之類的,且我在他的 Github 上看到最近一次 release 是 2021 感覺已經沒有在持續更新,索性就開始尋找替代方案。

這次要介紹的是可以更方便使用,並且有圖形介面的 Ultimate Vocal Remover GUI。

首先先到它的 Github 專案的 Releases 頁面下載安裝檔。Windows有兩個版本可選,一個是一般版,另一個是給有 AMD Radeon 或 Intel Arc 顯示卡的人使用的版本。

Mac 也有兩種版本,一個是 M1, M2 晶片 (arm64) 版,另一個是 Intel 晶片 (x86_64) 版。就看自己系統來決定下載哪一種。

裝完後,打開的畫面長這樣:

閱讀全文 把人聲與樂器分離的超強軟體 Ultimate Vocal Remover

[語言學習筆記] 中日英的數字單位(個十百千萬億兆)的唸法比較

這篇是由中、日文的數字表現方式,來對照英文的表現方式。首先先來了解各語言在數字單位上的不同、唸法的不同,後面會提供一個對照表。

很幸運地,日文跟中文對於數字的單位模式是一模一樣。唯一有例外的地方在於,當百跟千的數量是一時,不用把一唸出來,直接講百或千即可。但千的後面直接接著別的單位,例如「千萬」、「千億」等等,千前面的一還是得唸出來。

例如「168」唸作「ひゃく ろくじゅう はち」

例如「1,989」唸作「せん きゅうひゃく はちじゅう きゅう」

例如「12,000,000」唸作「せん にひゃく まん」

例如「10,000,000」唸作「いっせんまん」

注意到了嗎?一千兩百萬跟一千萬的唸法不同,一千兩百萬的情況下,千並非直接接著萬,因此還是可以省略唸一。一千萬就必須唸出一。

閱讀全文 [語言學習筆記] 中日英的數字單位(個十百千萬億兆)的唸法比較

[歌詞翻譯] 負けないで – Zard

ふとした瞬間に 視線がぶつかる
幸運(しあわせ)のときめき 覚えているでしょ
パステルカラーの季節に恋した
あの日のように 輝いてる あなたでいてね

突然一瞬間 對到了眼
那幸福的悸動 你還記得吧
在粉色系的季節相愛
你要持續跟那天一樣閃耀喔

閱讀全文 [歌詞翻譯] 負けないで – Zard

[歌詞翻譯] 元気を出して – 竹内まりや

涙など見せない 強気なあなたを
そんなに悲しませた人は誰なの?
終りを告げた恋に すがるのはやめにして
ふりだしから また始めればいい
幸せになりたい気持ちがあるなら
明日を見つけることは とても簡単

是誰,把不想讓人看到流淚、愛逞強的你
弄得如此悲傷呢?
別再執著於告終的戀情
只要再次從原點出發就好了
如果有心想變幸福的話
找尋明天是非常簡單的

閱讀全文 [歌詞翻譯] 元気を出して – 竹内まりや

[歌詞翻譯] アイドル IDOL – YOASOBI

無敵の笑顔で荒らすメディア
知りたいその秘密ミステリアス
抜けてるとこさえ彼女のエリア
完璧で嘘つきな君は
天才的なアイドル様

用無敵的笑容橫掃媒體版面
大家想知道的秘密,被她搞得像謎團一樣
連冒失這點,都在她能掌控的領域
你能如此完美的說謊
真的是天才般的IDOL大大

閱讀全文 [歌詞翻譯] アイドル IDOL – YOASOBI

[歌詞翻譯] 世界が終るまでは… – WANDS

大都会に 僕はもう一人で
投げ捨てられた 空きカンのようだ
互いのすべてを 知りつくすまでが
愛ならば いっそ 永久(とわ)に眠ろうか…

在大都市中,我已孤零零一人
就像被丟棄的空罐
如果要解彼此的一切才算是愛的話
那麼乾脆就讓我永遠長眠吧…

閱讀全文 [歌詞翻譯] 世界が終るまでは… – WANDS

[css筆記] 多行的情況下使用刪節號

上次介紹過如何在表格中使用刪節號,然而之前介紹的這個刪節號的方式,因搭配white-space: nowrap,使得我們使用刪節號會被限制在一行內。這次想要介紹的是在多行的情況下使用刪節號。

這次會使用到的屬性或值會需要加上 webkit prefix,分別是:display: -webkit-box,-webkit-line-clamp: 2, -webkit-box-orient: vertical,因為都還不是標規,亦或者是已經在css level3中有制定,但各家瀏覽器還是暫時只支援加上prefix的版本。例如 line-clamp,我們用caniuse查一下,可以看到他已經制定了,但不管是在edge, firefox, safari, chrome等等的瀏覽器,都還是必須加上prefix。

我們要做的很簡單,就是把 white-space: nowrap 拿掉,原本的 overflow: hidden; text-overflow: ellipsis; 保留,並加上 display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; 即可。

以下來解釋一下個屬性或值的意義。

display: -webkit-box; 其實就是個跟 display: flex 類似的東西,都是讓你可以做彈性編排的屬性值。但在此如果我們換成 flex,刪節號會失效。

-webkit-line-clamp 用於限制內文行數。

-webkit-box-orient: vertical; 以垂直 (vertical) 還是水平 (horizontal) 的方式排列內容

以下是範例程式碼:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .text {
      overflow: hidden;
      text-overflow: ellipsis;
      display: -webkit-box;
      -webkit-line-clamp: 2;
      -webkit-box-orient: vertical;
    }
  </style>
</head>
<body>
  <div class="text">
    最後,當他們回到了小咖啡的家中時,天已經亮了。小咖啡感激地對彩虹說:“謝謝你陪我一起冒險,如果沒有你,我可能永遠都找不到回家的路。”而彩虹笑著回答說:“沒關係,朋友就應該互相幫助。”他們相擁而睡,帶著對未來的無限期待。小雨班聽完這個故事後,眼皮漸漸變得沉重,他靜靜地閉上了眼睛,腦海中充滿了對動物冒險的美好幻想。最後,他甜甜地入睡了,做著美好的夢境。
  </div>
</body>
</html>