<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>XEYcmd · 文章</title>
    <link>https://blog.xeycmd.ccwu.cc/posts/</link>
    <atom:link href="https://blog.xeycmd.ccwu.cc/rss.xml" rel="self" type="application/rss+xml" />
    <description>XEYcmd 的个人网站：代码、终端与二次元的记录。</description>
    <language>zh-CN</language>
    <lastBuildDate>Tue, 20 Oct 2026 00:00:00 GMT</lastBuildDate>
    <image>
      <url>https://blog.xeycmd.ccwu.cc/og.png</url>
      <title>XEYcmd</title>
      <link>https://blog.xeycmd.ccwu.cc/</link>
    </image>
    <item>
      <title>你好，世界</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/hello-world/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/hello-world/</guid>
      <pubDate>Tue, 20 Oct 2026 00:00:00 GMT</pubDate>
      <description>第一篇文章：为什么要搭这个站，以及这个站会写些什么。</description>
      <content:encoded><![CDATA[<h1>你好，世界</h1>
<p>这是这个站点的第一篇文章。写它的时候，首页的轮换背景还没换上真正的插画，只有一层紫色的渐变光。</p>
<h2 id="为什么要自己搭一个站">为什么要自己搭一个站<a class="anchor" href="#为什么要自己搭一个站" aria-hidden="true">#</a></h2>
<p>平台很好用，但总有些东西不适合放在别人的时间线上：写过的小工具、踩过的坑、半夜三点想明白的一件事。放在自己的域名下，它们至少不会因为平台改版而消失。</p>
<blockquote><p>有一个自己的角落，比在广场上喊话更舒服。</p></blockquote>
<h2 id="这个站会写什么">这个站会写什么<a class="anchor" href="#这个站会写什么" aria-hidden="true">#</a></h2>
<ul><li>写代码时踩到的坑，以及最后怎么绕过去的</li><li>折腾各种工具的记录（比如这次搭站本身）</li><li>一些和代码无关的、二次元相关的东西</li></ul>
<h2 id="技术上是这样的">技术上是这样的<a class="anchor" href="#技术上是这样的" aria-hidden="true">#</a></h2>
<p>整站是纯静态的：<code>npm run build</code> 生成一堆 HTML，推到 GitHub 之后由 Actions 自动发布到 GitHub Pages。</p>
<pre><div class="code-head"><span>bash</span></div><code class="language-bash">npm install
npm run dev      # 本地预览
npm run build    # 生成 dist/</code></pre>
<p>发文章只要往 <code>content/posts/</code> 里丢一个 Markdown 文件：</p>
<pre><div class="code-head"><span>md</span></div><code class="language-md">---
title: 文章标题
date: 2026-10-21
lang: zh
summary: 一句话摘要
tags: [标签]
---

正文从这里开始。</code></pre>
<p>写完 push 上去，几分钟后线上就有了。</p>
<h2 id="接下来">接下来<a class="anchor" href="#接下来" aria-hidden="true">#</a></h2>
<ul><li>换上真正的背景插画</li><li>把文章的代码块做个高亮主题</li><li>或许再加个评论区</li></ul>
<p>先这样，剩下的慢慢来。</p>]]></content:encoded>
    </item>
    <item>
      <title>给纯静态站点加一点“活”的东西</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/css-canvas-motion/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/css-canvas-motion/</guid>
      <pubDate>Sun, 18 Oct 2026 00:00:00 GMT</pubDate>
      <description>交叉淡入淡出的背景、打字机效果、樱花粒子——全部用 CSS 和原生 Canvas 实现，不需要任何动画库。</description>
      <content:encoded><![CDATA[<h1>给纯静态站点加一点&quot;活&quot;的东西</h1>
<p>首页想要的效果有四个：背景轮换、打字机标题、飘落的樱花、跟着鼠标的光点。它们都可以不装任何依赖就做出来。</p>
<h2 id="背景-纯-css-就能交叉淡入淡出">背景：纯 CSS 就能交叉淡入淡出<a class="anchor" href="#背景-纯-css-就能交叉淡入淡出" aria-hidden="true">#</a></h2>
<p>关键是把每张图放在独立的一层上，然后用同一个 <code>animation</code> 但不同的 <code>animation-delay</code> 错开：</p>
<pre><div class="code-head"><span>css</span></div><code class="language-css">.bg--has-images .bg__layer {
  background-image: var(--bg-url);
  animation:
    bg-show var(--duration) ease-in-out var(--delay) infinite both,
    kenburns calc(var(--duration) * 2) ease-in-out infinite alternate;
}

@keyframes bg-show {
  0%   { opacity: 0; }
  3%   { opacity: 1; }
  50%  { opacity: 1; }
  58%, 100% { opacity: 0; }
}</code></pre>
<p><code>bg-show</code> 里 3% 到 50% 是全不透明，58% 之后完全透明。因为相邻两层的透明区间有重叠，叠化时两张图会同时可见——这就是交叉淡入淡出的来源。</p>
<blockquote><p>把图片数量 × 2 层叠起来，轮换的循环就接上了。</p></blockquote>
<h2 id="打字机-asyncawait-反而最清楚">打字机：async/await 反而最清楚<a class="anchor" href="#打字机-asyncawait-反而最清楚" aria-hidden="true">#</a></h2>
<pre><div class="code-head"><span>ts</span></div><code class="language-ts">const run = async () =&gt; {
  for (;;) {
    if (!deleting) {
      charIndex++;
      target.textContent = line.slice(0, charIndex);
      if (charIndex &gt;= line.length) {
        deleting = true;
        await pause(2200);
        continue;
      }
      await pause(85 + Math.random() * 70);
    } else {
      charIndex--;
      target.textContent = line.slice(0, Math.max(0, charIndex));
      if (charIndex &lt;= 0) {
        deleting = false;
        lineIndex = (lineIndex + 1) % lines.length;
        await pause(480);
        continue;
      }
      await pause(34 + Math.random() * 24);
    }
  }
};</code></pre>
<p>每次暂停的时长带一点随机，打出来就不会有机械感。</p>
<h2 id="樱花粒子-canvas-比-dom-便宜">樱花粒子：Canvas 比 DOM 便宜<a class="anchor" href="#樱花粒子-canvas-比-dom-便宜" aria-hidden="true">#</a></h2>
<p>七十个 DOM 元素做动画会掉帧，画在 Canvas 上就几乎不花钱：</p>
<pre><div class="code-head"><span>ts</span></div><code class="language-ts">const frame = (now: number) =&gt; {
  const dt = Math.min((now - last) / 1000, 0.05);
  last = now;
  ctx.clearRect(0, 0, w, h);

  for (const p of petals) {
    p.phase += dt * 0.9;
    p.y += p.speed * dt;
    p.x += Math.sin(p.phase) * p.sway * dt;
    p.rot += p.vr * dt;
    draw(p);
  }
  requestAnimationFrame(frame);
};</code></pre>
<p>花瓣用 <code>bezierCurveTo</code> 画一个不对称的椭圆，星星用四个二次贝塞尔拼出来。<code>z</code> 值决定大小、速度和透明度，制造纵深。</p>
<h2 id="别忘了尊重用户的偏好">别忘了尊重用户的偏好<a class="anchor" href="#别忘了尊重用户的偏好" aria-hidden="true">#</a></h2>
<p>所有动画都要在 <code>prefers-reduced-motion: reduce</code> 下退化成静态：</p>
<pre><div class="code-head"><span>css</span></div><code class="language-css">@media (prefers-reduced-motion: reduce) {
  .bg--has-images .bg__layer { animation: none; }
  .bg--has-images .bg__layer:first-child { opacity: 1; }
}</code></pre>
<pre><div class="code-head"><span>ts</span></div><code class="language-ts">if (reduceMotion.matches) {
  target.textContent = lines[0];
  return;
}</code></pre>
<h2 id="小结">小结<a class="anchor" href="#小结" aria-hidden="true">#</a></h2>
<div class="table-wrap"><table><thead><tr><th>效果</th><th>实现</th><th>依赖</th></tr></thead><tbody><tr><td>背景轮换</td><td>CSS animation</td><td>无</td></tr><tr><td>打字机</td><td>async/await + setTimeout</td><td>无</td></tr><tr><td>樱花粒子</td><td>Canvas 2D</td><td>无</td></tr><tr><td>光点拖尾</td><td>Canvas 2D + pointermove</td><td>无</td></tr></tbody></table></div>
<p>四个效果，零依赖，整站 JS 加起来不到 12KB。</p>]]></content:encoded>
    </item>
    <item>
      <title>把写作流程收进 Git</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/markdown-workflow/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/markdown-workflow/</guid>
      <pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate>
      <description>用 Markdown + git push 发文章之后，写作变成了一次提交，历史、回滚、协作都免费得到。</description>
      <content:encoded><![CDATA[<h1>把写作流程收进 Git</h1>
<p>用 Markdown + git push 发文章之后，写作变成了一次提交，历史、回滚、协作都免费得到。</p>
<h2 id="正文">正文<a class="anchor" href="#正文" aria-hidden="true">#</a></h2>
<p>这里放正文内容。详细内容请到文章页查看。</p>]]></content:encoded>
    </item>
    <item>
      <title>静态站部署的三个坑</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/static-site-deploy/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/static-site-deploy/</guid>
      <pubDate>Mon, 12 Oct 2026 00:00:00 GMT</pubDate>
      <description>自定义域、HTTPS 证书、子路径——部署到 GitHub Pages 时最容易卡住的三件事。</description>
      <content:encoded><![CDATA[<h1>静态站部署的三个坑</h1>
<p>自定义域、HTTPS 证书、子路径——部署到 GitHub Pages 时最容易卡住的三件事。</p>
<h2 id="正文">正文<a class="anchor" href="#正文" aria-hidden="true">#</a></h2>
<p>这里放正文内容。详细内容请到文章页查看。</p>]]></content:encoded>
    </item>
    <item>
      <title>我的终端配置</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/terminal-setup/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/terminal-setup/</guid>
      <pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate>
      <description>从 PowerShell 到 Windows Terminal，记一份够用就好、不折腾的配置。</description>
      <content:encoded><![CDATA[<h1>我的终端配置</h1>
<p>从 PowerShell 到 Windows Terminal，记一份够用就好、不折腾的配置。</p>
<h2 id="正文">正文<a class="anchor" href="#正文" aria-hidden="true">#</a></h2>
<p>这里放正文内容。详细内容请到文章页查看。</p>]]></content:encoded>
    </item>
    <item>
      <title>2026 年读过的几本书</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/reading-notes-2026/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/reading-notes-2026/</guid>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
      <description>技术之外的一些阅读记录，以及它们留下的印象。</description>
      <content:encoded><![CDATA[<h1>2026 年读过的几本书</h1>
<p>技术之外的一些阅读记录，以及它们留下的印象。</p>
<h2 id="正文">正文<a class="anchor" href="#正文" aria-hidden="true">#</a></h2>
<p>这里放正文内容。详细内容请到文章页查看。</p>]]></content:encoded>
    </item>
    <item>
      <title>番剧与代码的相似之处</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/anime-notes/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/anime-notes/</guid>
      <pubDate>Sun, 20 Sep 2026 00:00:00 GMT</pubDate>
      <description>追番和写代码其实很像：都在等一个恰到好处的转折。</description>
      <content:encoded><![CDATA[<h1>番剧与代码的相似之处</h1>
<p>追番和写代码其实很像：都在等一个恰到好处的转折。</p>
<h2 id="正文">正文<a class="anchor" href="#正文" aria-hidden="true">#</a></h2>
<p>这里放正文内容。详细内容请到文章页查看。</p>]]></content:encoded>
    </item>
    <item>
      <title>为什么值得有一个自己的域名</title>
      <link>https://blog.xeycmd.ccwu.cc/posts/why-personal-site/</link>
      <guid isPermaLink="true">https://blog.xeycmd.ccwu.cc/posts/why-personal-site/</guid>
      <pubDate>Sat, 12 Sep 2026 00:00:00 GMT</pubDate>
      <description>平台会改版、账号会消失，但一个属于自己的地址可以留很久。</description>
      <content:encoded><![CDATA[<h1>为什么值得有一个自己的域名</h1>
<p>平台会改版、账号会消失，但一个属于自己的地址可以留很久。</p>
<h2 id="正文">正文<a class="anchor" href="#正文" aria-hidden="true">#</a></h2>
<p>这里放正文内容。详细内容请到文章页查看。</p>]]></content:encoded>
    </item>
  </channel>
</rss>