大版本更新
一口气全面统一博客样式,移除部分冗余导航页面,更专注内容展示。
不因虚度年华而悔恨,不因碌碌无为而羞愧
把首页的拼图底纹搬进显示设置的七种纹理、修掉卡片等高与备案错位、给卡通角色换上自己的头像并补上点击喵声、把关于页的致谢补全到 Shirone,最后让 mmz 成为默认皮肤——每一处都按零额外负担来做。
首页复刻完之后,剩下一堆「看着别扭但说不上哪里错」的小问题:首屏底纹只活在一个页面里、近期文章和动态两列高度不齐、页脚备案号挤成一团、卡通人物点下去毫无反馈、关于页少写了一个项目。
这篇记录这几处打磨,以及最后把 mmz 设成默认皮肤的做法。
首页的拼图底纹原本写死在 mmz 皮肤的 body 上,只有首页能看到。这次把它提升成通用能力:
src/styles/textures.css 定义纹理预设;TEXTURE_PRESETS / TexturePreset 给出类型与白名单;Layout.astro 首帧把 data-texture-preset 写到 <html>;DisplaySettings.svelte 的「外观 → 背景纹理」提供切换入口;七种预设立在那儿:无、网格、点阵、噪点、斜纹、波纹,以及这次的拼图。

首页的拼图蒙版是一个周期 224px 的 SVG:112×112 的 pattern 里排两块 56px 的拼图块,卡榫与凹槽交替。为了保证「显示设置里的这个背景」和首页看起来是同一张图,纹理预设没有去重画一遍,而是把同一份路径数据内联进 textures.css:
1html[data-texture-preset="jigsaw"] #m3e-texture-canvas {2 -webkit-mask-image: url("data:image/svg+xml;...");3 mask-image: url("data:image/svg+xml;...");4 mask-size: 224px 224px;5}好处是不多发一个网络请求,也不会因为图片加载晚到而先闪一下空白;代价是 CSS 里多了一段长字符串,所以只给拼图这一个「和首页同源」的预设开了特例。
mmz 皮肤原来有一张自己的 body 底图,还会把通用纹理层藏起来。这轮把两处都删了,所有页面统一走 #m3e-texture-canvas。切页时 Swup 只换内容,纹理层在持久外壳里,不会重渲染,也就不会有「切页纹理闪一下」的问题。

默认预设同时改成了 jigsaw,新访客第一次进来看到的底纹就和首页一致。
「近期文章」和「我的动态」两列高度不齐,根因是两边都用内容撑高,列表长度不同就错位。改成两列等高 + 面板内部纵向 flex:
1.mmz-afterglow__col { display: flex; }2.mmz-afterglow__panel { display: flex; flex-direction: column; flex: 1; }3.mmz-afterglow__list { flex: 1; overflow-y: auto; max-height: 25rem; }白底则是另一回事:面板默认吃了卡片底色,压在拼图纹理上就是一块突兀的白。这次把面板底色去掉,只留细描边,纹理透上来之后和首屏观感接上了。
新头像是 1504×1664 的透明 PNG,而角色槽位是 1:1 的正方形。直接塞进去会被裁掉耳朵,强行拉伸又会变形。
做法是「等比缩放 + 横向透明补边」:先按高度缩到 1254,再在左右补透明边凑成 1254×1254,导出 AVIF。尺寸和原槽位完全一致,所以布局一行没改,实测渲染仍是 192×192。
顺带验证了一下透明边缘:把图 flatten 到品红底上看,没有白边残留。
参考站的角色点下去会有反馈,这里补上的是声音。第一版踩了个坑:
1const src = await resolveAsset("themes/mmz/assets/dialogue/meow.mp3");resolveAsset 只对图片做 glob,音频会被原样返回成相对路径,浏览器直接 404。改用 Vite 的资源导入:
1import dialogueSoundSrc from "../assets/dialogue/meow.mp3?url";再把结果通过 data-dialogue-sound 传给控制器。播放策略按零额外负担处理:
currentTime = 0 重头播,音量 0.55;play() 被自动播放策略拦下来时静默忽略,换词照常进行;destroy 时 pause() 并置空。音频本身是 Windows 中文 TTS 生成的一声「喵~」,再用 ffmpeg 裁掉尾部静音、升调、淡出,最后是 0.348 秒、3.5KB 的 mp3,内置在主题资源里。

把 mmz 变成默认皮肤,改的不是代码而是配置。本项目的配置是「内容仓覆盖」模式:内容仓里的 config/site-theme.yaml 是来源,src/user/user-config.ts 是 content:sync 的生成物,不能手改。
1enable: true2defaultTheme: mmz改完跑一次同步:
1pnpm.cmd content:sync同步后重新开会话实测:data-site-theme="mmz"、首页命中 mmz 变体、壁纸模式为 none。访客仍然可以在显示设置里切回默认皮肤,只是「第一次进来看到的」变成了 mmz。
关于页原本写「借鉴了两位大佬」,但真正支撑整站组件体系的其实是第三个项目。这次补成三位:
三家都用 ::github{repo="..."} 生成仓库卡片,构建期抓取,运行时不发请求。

这一轮没有大功能,全是「把已有的东西收干净」:纹理从单页变成站点能力、两列卡片对齐、角色有了自己的脸和声音、致谢写全、默认皮肤换成自己最满意的那个。
原则还是那条:可选的东西默认零负担。纹理能关、声音没点过就不加载、仓库卡片构建期抓完就静态化——关掉它们时,站点不该多一行 DOM、一个请求、一字节包体。
全部改动走 npx.cmd astro check(0 errors)+ Playwright 实测 + pnpm.cmd build 验证后上线。
生成精美分享图或复制链接,与更多人分享本文。
最后更新于 ,距今已过 0 天
部分内容可能已过时