# 含部落格的個人頁

多頁式個人網站（首頁、作品集、部落格、文章），以 PDRenderKit 1.2.0 組合片段，含 JS 瀑布流與 Markdown 檢視器。

## 概要

| 項目 | 內容 |
|---|---|
| 製作日期 | 2023-06-21 |
| 分類 | 部落格範例 |
| HTML 檔案 | `index.html`, `portfolio.html`, `blog.html`, `blog-content.html`, `view/nav.html`, `view/header.html`, `view/portfolio.html`, `view/service.html`, `view/about.html`, `view/skill.html`, `view/client.html`, `view/contact.html`, `view/footer.html`, `view/blog-content.html` |
| 原始碼 | [target/20230621](https://github.com/pardnio/demo-web/tree/main/target/20230621) |

## 即時預覽

<iframe src="/target/20230621/" title="含部落格的個人頁" loading="lazy" style="width:100%;height:640px;border:1px solid #e5e7eb;border-radius:8px"></iframe>

[在新分頁開啟範例](/target/20230621/)

## 頁面區塊

| 區塊 | 說明 |
|---|---|
| 導覽列（view/nav.html） | sticky 導覽列，品牌連結與 :for 渲染的 HOME / PORTFOLIO / BLOG；800px 以下由漢堡 @click=tab 開關選單。 |
| 主視覺（view/header.html） | 標題、副標與 GitHub / LinkedIn 按鈕，含進場動畫。 |
| 作品集（view/portfolio.html） | 依頁面全域 ary（首頁 8 筆、portfolio.html 24 筆）產生的 JS 瀑布流佔位圖，並自動建立 ALL/TAG1/TAG2/TAG3 篩選分頁。 |
| 服務（view/service.html） | 以 :for 依圖示名稱渲染 6 個項目，class 使用插值 fa-{{ e }}。 |
| 關於（view/about.html） | 照片搭配 image/about.svg 裝飾、自介與兩組 3 項時間軸。 |
| 技能（view/skill.html） | 8 個圓餅指標，:year 值 1..8 隨機排序，進場時播放動畫。 |
| 客戶評價（view/client.html） | 5 張評價卡的橫向循環輪播，附前後按鈕。 |
| 聯絡（view/contact.html） | :model 表單（名稱、Email、訊息）以 @click=send 跳出 alert，旁為嵌入的 Google 地圖 iframe。 |
| 頁尾（view/footer.html） | 版權與 :for 圖示連結（GitHub、LinkedIn、Mail）。 |
| 部落格列表（blog.html） | 雙欄：作者卡、8 篇連到 blog-content.html 的文章、上下頁；側欄含搜尋、最新 4 篇、主題與標籤；行動版底部浮動搜尋列。 |
| 文章頁（blog-content.html + view/blog-content.html） | 文章標題、details/summary 索引、以 PDMarkdownKit viewer 顯示 PDMarkdownKit README、上下篇連結與相同側欄。 |

## 互動行為

- js/index.js 與 js/blog.js 以導覽資料建立 new PD({id: "body"})；各 view/*.html 的 script 建立自己的 PD 實例，並在 next() 將 *.delay 元素註冊到共用 delay_observer。
- 進場：IntersectionObserver 移除 .delay，700ms 後設定 done=1（::after 擦除遮罩），1300ms 後移除 .at；技能圓餅依 [done="1"][year] 播放動畫。
- updateShadow()：依 body 捲動位置（0..32px）漸變 nav 與 .float-bottom 的陰影。
- view/portfolio.html：絕對定位瀑布流，每項放入最短欄（&lt;480 / 480 / 1024px 為 1/2/3 欄），標籤分頁設定 filter-key 後由 updatePortfolio() 以透明度重新排版，window.onresize 防抖 300ms 重排。
- view/client.html：複製卡片做無限循環，前後按鈕以 setInterval（10ms）動畫 scrollLeft，到端點時跳回中段副本。
- js/blog.js（module）：抓取 https://cdn.jsdelivr.net/npm/pdmarkdownkit@1.6.0/README.md，在含 section[name=blog-content] 的頁面於 section.page 前掛載 PDMarkdownKit viewer；側欄高於視窗時調整 sticky top。
- js/blog.js 的 tab 事件為箭頭函式卻使用 this.$pre()，部落格頁的行動選單切換沒有元素可作為 this。

## 相依資源

| 名稱 | 版本 | 來源 |
|---|---|---|
| Font Awesome Free | 6.5.2 | https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@6.5.2/css/all.min.css |
| PDRenderKit | 1.2.0 | https://cdn.jsdelivr.net/npm/pdrenderkit@1.2.0/dist/PDRenderKit.js |
| PDMarkdownKit (ES module, blog pages) | 1.6.0 | https://cdn.jsdelivr.net/npm/pdmarkdownkit@1.6.0/dist/PDMarkdownKit.module.js |
| Google Maps embed iframe | - | https://www.google.com/maps/embed?pb=... |
| Google Analytics (gtag.js) | - | https://www.googletagmanager.com/gtag/js?id=G-L5VYEZPVXX |
| js/index.js (index.html, portfolio.html) | - | ./js/index.js |
| js/blog.js (blog.html, blog-content.html) | - | ./js/blog.js (type=module) |

## 樣式

| 項目 | 內容 |
|---|---|
| SCSS 入口 | `sass/index.scss` |
| 輸出 CSS | `css/index.css` |
| Partials | `function/_hsbTohsl.scss`, `_init.scss`, `_nav.scss`, `_header.scss`, `_blog.scss`, `_portfolio.scss`, `_service.scss`, `_about.scss`, `_skill.scss`, `_client.scss`, `_contact.scss`, `_footer.scss`, `animation/_section-3.scss`, `animation/_pie.scss`, `animation/_bg-move.scss` |

function/_hsbTohsl 定義 HSB 轉 HSL 的 hsb()/hsba() SCSS 函式；_init 含 reset、斷點變數（$_800: 50rem 等）與 HSB 推導色階（brand/success/notify/error/info/border）。index.scss 定義全域 .at/.delay/[done] 進場效果（::after 漸層擦除）與旋轉 a.hint 浮水印。_skill @import animation/_pie 並以 @for 依 [done][year] 旋轉圓餅；_blog 涵蓋列表／文章／sticky 側欄、details 索引與 .float-bottom；_client 處理 [row] 版面。animation/_bg-move 存在但未被 import。inline &lt;style&gt; 設定 --col-brand-5 #f1c50e 與 --gradient-col。

```bash
cd target/20230621
npx sass sass/index.scss css/index.css --no-source-map || exit 1
```

## 使用技巧

- PDRenderKit PD 模板：:path 片段、:for、{{ }}（含屬性內插值 :class="... fa-{{ e }}"）、:model、@click、next() 生命週期。
- 自訂 SCSS @function 將 HSB 轉 HSL 並產生色階。
- JS 計算最短欄的絕對定位瀑布流；以 opacity/left 過渡篩選。
- 擦除進場效果：::after 使用 300% 三段漸層，透過 [done] 屬性改變 background-position。
- details/summary 索引、sticky 導覽與側欄、backdrop-filter，斷點 max-width 799.99px 與 min-width 480/640/800/1024px。

## 外部資源

- https://cdn.jsdelivr.net/npm/pdmarkdownkit@1.6.0/README.md (fetched as blog post content)
- https://www.google.com/maps/embed?pb=... (contact map iframe)
- https://fakeimg.pl/1024/282828/eae0d0/?text=sample (placeholder images)
- https://pardn.io/image/head.png (favicon)
- https://pardn.io/web-template/image/20230621.jpg (og/twitter image)

## 相關頁面

- [專案結構](/zh/project-structure)
- [樣式工作流程](/zh/styling-workflow)
- [框架使用](/zh/frameworks)
