541 lines
17 KiB
HTML
541 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>窗户反光中偶见的现象 — 看不清的事情</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
<script>
|
|
tailwind.config = {
|
|
theme: {
|
|
extend: {
|
|
colors: {
|
|
bg: '#f5f4f0',
|
|
dark: '#1a1a1a',
|
|
accent: '#6b7280',
|
|
muted: '#9ca3af',
|
|
subtle: '#e5e5e3',
|
|
},
|
|
fontFamily: {
|
|
serif: ['Noto Serif SC', 'serif'],
|
|
sans: ['Noto Sans SC', 'Inter', 'sans-serif'],
|
|
mono: ['JetBrains Mono', 'monospace'],
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
html { scroll-behavior: smooth; }
|
|
body {
|
|
background: #f5f4f0;
|
|
color: #1a1a1a;
|
|
font-family: 'Noto Sans SC', 'Inter', sans-serif;
|
|
}
|
|
::selection { background: #1a1a1a; color: #f5f4f0; }
|
|
|
|
/* 顶栏 */
|
|
.top-bar {
|
|
position: fixed;
|
|
top: 0; left: 0; right: 0;
|
|
height: 48px;
|
|
background: rgba(245, 244, 240, 0.92);
|
|
backdrop-filter: blur(12px);
|
|
-webkit-backdrop-filter: blur(12px);
|
|
border-bottom: 1px solid #e5e5e3;
|
|
z-index: 100;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 32px;
|
|
}
|
|
.top-bar-left { display: flex; align-items: center; gap: 20px; }
|
|
.back-link {
|
|
font-size: 12px; color: #9ca3af; text-decoration: none;
|
|
letter-spacing: 0.08em; display: flex; align-items: center; gap: 6px;
|
|
transition: color 0.3s; cursor: pointer;
|
|
}
|
|
.back-link:hover { color: #1a1a1a; }
|
|
.back-arrow { display: inline-block; transition: transform 0.3s ease; }
|
|
.back-link:hover .back-arrow { transform: translateX(-3px); }
|
|
.top-bar-index {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 11px; color: #d1d5db; letter-spacing: 0.15em;
|
|
}
|
|
.top-bar-right {
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: 12px; color: #9ca3af; letter-spacing: 0.12em;
|
|
}
|
|
|
|
/* 进度条 */
|
|
.progress-bar {
|
|
position: fixed;
|
|
top: 48px; left: 0;
|
|
height: 1px; background: #1a1a1a;
|
|
z-index: 101; width: 0%;
|
|
transition: width 0.05s linear;
|
|
}
|
|
|
|
/* 文章元信息 */
|
|
.article-meta {
|
|
max-width: 680px;
|
|
margin: 0 auto;
|
|
padding: 120px 24px 0;
|
|
margin-bottom: 48px;
|
|
}
|
|
.article-category {
|
|
font-size: 11px; color: #9ca3af;
|
|
letter-spacing: 0.2em; text-transform: uppercase;
|
|
font-family: 'Inter', sans-serif;
|
|
margin-bottom: 24px;
|
|
}
|
|
.article-category span {
|
|
display: inline-block;
|
|
padding-bottom: 2px;
|
|
border-bottom: 1px solid #d1d5db;
|
|
}
|
|
.article-info {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
padding-top: 24px;
|
|
border-top: 1px solid #e5e5e3;
|
|
margin-top: 32px;
|
|
}
|
|
.info-item {
|
|
font-size: 12px; color: #9ca3af; letter-spacing: 0.05em;
|
|
}
|
|
.info-item strong { color: #6b7280; font-weight: 500; }
|
|
.info-dot { width: 3px; height: 3px; background: #d1d5db; border-radius: 50%; }
|
|
|
|
/* Markdown 正文容器 */
|
|
.article-body-wrap {
|
|
max-width: 680px;
|
|
margin: 0 auto;
|
|
padding: 0 24px 80px;
|
|
}
|
|
|
|
/* ——— Markdown 渲染样式 ——— */
|
|
.md h1 {
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: clamp(28px, 5vw, 42px);
|
|
font-weight: 600;
|
|
line-height: 1.4;
|
|
letter-spacing: -0.01em;
|
|
color: #1a1a1a;
|
|
margin-bottom: 12px;
|
|
}
|
|
.md h2 {
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: #1a1a1a;
|
|
margin-top: 3em;
|
|
margin-bottom: 1.5em;
|
|
padding-left: 20px;
|
|
position: relative;
|
|
}
|
|
.md h2::before {
|
|
content: '';
|
|
position: absolute; left: 0; top: 0.4em;
|
|
width: 8px; height: 8px;
|
|
border: 1.5px solid #1a1a1a;
|
|
border-radius: 50%;
|
|
}
|
|
.md h3 {
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: 19px;
|
|
font-weight: 600;
|
|
color: #1a1a1a;
|
|
margin-top: 2.2em;
|
|
margin-bottom: 1em;
|
|
}
|
|
.md h4, .md h5, .md h6 {
|
|
font-family: 'Noto Sans SC', sans-serif;
|
|
font-size: 15px; font-weight: 500;
|
|
color: #6b7280;
|
|
margin-top: 2em; margin-bottom: 0.8em;
|
|
letter-spacing: 0.05em;
|
|
}
|
|
.md p {
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: 17px;
|
|
line-height: 2.2;
|
|
color: #374151;
|
|
margin-bottom: 1.8em;
|
|
text-align: justify;
|
|
}
|
|
.md p:first-of-type {
|
|
margin-top: 0;
|
|
}
|
|
.md blockquote {
|
|
margin: 2.2em 0;
|
|
padding: 20px 0 20px 24px;
|
|
border-left: 1px solid #1a1a1a;
|
|
color: #6b7280;
|
|
font-size: 16px;
|
|
line-height: 2;
|
|
}
|
|
.md blockquote p { margin-bottom: 0; font-size: 16px; color: #6b7280; }
|
|
.md strong { font-weight: 600; color: #1a1a1a; }
|
|
.md em { font-style: italic; }
|
|
.md a {
|
|
color: #6b7280;
|
|
border-bottom: 1px solid #d1d5db;
|
|
text-decoration: none;
|
|
transition: all 0.3s;
|
|
}
|
|
.md a:hover { color: #1a1a1a; border-bottom-color: #1a1a1a; }
|
|
.md ul, .md ol {
|
|
margin: 1.5em 0;
|
|
padding-left: 1.5em;
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: 17px;
|
|
line-height: 2.2;
|
|
color: #374151;
|
|
}
|
|
.md li { margin-bottom: 0.3em; }
|
|
.md ul li::marker { color: #9ca3af; }
|
|
.md ol li::marker { color: #9ca3af; font-family: 'JetBrains Mono', monospace; font-size: 13px; }
|
|
.md code {
|
|
font-family: 'JetBrains Mono', monospace;
|
|
font-size: 13px;
|
|
background: #eeedea;
|
|
padding: 2px 6px;
|
|
border-radius: 2px;
|
|
color: #6b7280;
|
|
}
|
|
.md pre {
|
|
margin: 2em 0;
|
|
background: #1e1e1e;
|
|
padding: 24px;
|
|
border-radius: 2px;
|
|
overflow-x: auto;
|
|
}
|
|
.md pre code {
|
|
background: transparent;
|
|
padding: 0;
|
|
color: #d4d4d4;
|
|
font-size: 13px;
|
|
line-height: 1.8;
|
|
}
|
|
.md hr {
|
|
border: none;
|
|
height: 1px;
|
|
background: #e5e5e3;
|
|
margin: 3em 0;
|
|
}
|
|
.md img {
|
|
max-width: 100%;
|
|
display: block;
|
|
margin: 2em auto;
|
|
filter: grayscale(40%) contrast(0.95);
|
|
opacity: 0.8;
|
|
transition: all 0.6s ease;
|
|
}
|
|
.md img:hover { filter: grayscale(20%) contrast(1); opacity: 1; }
|
|
.md table {
|
|
width: 100%;
|
|
margin: 2em 0;
|
|
border-collapse: collapse;
|
|
font-size: 14px;
|
|
font-family: 'Noto Sans SC', sans-serif;
|
|
}
|
|
.md th {
|
|
text-align: left;
|
|
font-weight: 500;
|
|
font-size: 11px;
|
|
color: #9ca3af;
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
padding: 12px 16px;
|
|
border-bottom: 2px solid #1a1a1a;
|
|
}
|
|
.md td {
|
|
padding: 12px 16px;
|
|
border-bottom: 1px solid #e5e5e3;
|
|
color: #374151;
|
|
}
|
|
.md tr:hover td { background: #fafaf8; }
|
|
|
|
/* 结尾标记 */
|
|
.article-end {
|
|
text-align: center;
|
|
padding-top: 48px;
|
|
margin-top: 48px;
|
|
border-top: 1px solid #e5e5e3;
|
|
}
|
|
.end-mark {
|
|
display: inline-block;
|
|
width: 6px; height: 6px;
|
|
background: #1a1a1a;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
/* 上下篇导航 */
|
|
.article-nav {
|
|
max-width: 680px;
|
|
margin: 0 auto;
|
|
padding: 0 24px;
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 1px;
|
|
background: #e5e5e3;
|
|
border-top: 1px solid #e5e5e3;
|
|
margin-bottom: 80px;
|
|
}
|
|
.nav-card {
|
|
background: #f5f4f0;
|
|
padding: 40px 32px;
|
|
text-decoration: none;
|
|
transition: background 0.3s ease;
|
|
cursor: pointer;
|
|
}
|
|
.nav-card:hover { background: #fafaf8; }
|
|
.nav-card:hover .nav-card-title { color: #1a1a1a; }
|
|
.nav-card:hover .nav-card-arrow { opacity: 1; transform: translateX(0); }
|
|
.nav-card-label {
|
|
font-size: 11px; color: #9ca3af;
|
|
letter-spacing: 0.15em; margin-bottom: 16px;
|
|
font-family: 'Inter', sans-serif;
|
|
}
|
|
.nav-card-title {
|
|
font-family: 'Noto Serif SC', serif;
|
|
font-size: 16px; color: #6b7280; font-weight: 500;
|
|
transition: color 0.3s; line-height: 1.6;
|
|
}
|
|
.nav-card-arrow {
|
|
margin-top: 16px; font-size: 13px; color: #1a1a1a;
|
|
opacity: 0; transform: translateX(-6px);
|
|
transition: all 0.3s ease;
|
|
}
|
|
.nav-card.next { text-align: right; }
|
|
.nav-card.next .nav-card-arrow { transform: translateX(6px); }
|
|
.nav-card.next:hover .nav-card-arrow { transform: translateX(0); }
|
|
|
|
/* 页脚 */
|
|
.site-footer {
|
|
max-width: 680px;
|
|
margin: 0 auto;
|
|
padding: 32px 24px 48px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
border-top: 1px solid #e5e5e3;
|
|
font-size: 11px; color: #d1d5db; letter-spacing: 0.1em;
|
|
}
|
|
|
|
/* 滚动动画 */
|
|
.reveal {
|
|
opacity: 0;
|
|
transform: translateY(16px);
|
|
transition: all 0.7s cubic-bezier(0.16, 1, 0.3, 1);
|
|
}
|
|
.reveal.visible { opacity: 1; transform: translateY(0); }
|
|
|
|
/* Toast */
|
|
.toast {
|
|
position: fixed; bottom: 32px; left: 50%;
|
|
transform: translateX(-50%) translateY(100px);
|
|
background: #1a1a1a; color: #f5f4f0;
|
|
padding: 12px 24px; font-size: 13px;
|
|
border-radius: 2px; z-index: 9999;
|
|
transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
|
pointer-events: none; letter-spacing: 0.05em;
|
|
}
|
|
.toast.show { transform: translateX(-50%) translateY(0); }
|
|
|
|
/* 响应式 */
|
|
@media (max-width: 768px) {
|
|
.article-meta { padding-top: 96px; }
|
|
.md h1 { font-size: 26px; }
|
|
.md h2 { font-size: 20px; }
|
|
.md p { font-size: 16px; line-height: 2; }
|
|
.article-nav { grid-template-columns: 1fr; }
|
|
.nav-card.next { text-align: left; }
|
|
.nav-card.next .nav-card-arrow { transform: translateX(-6px); }
|
|
.nav-card.next:hover .nav-card-arrow { transform: translateX(0); }
|
|
.top-bar { padding: 0 16px; }
|
|
.article-info { flex-wrap: wrap; gap: 12px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<!-- 顶栏 -->
|
|
<header class="top-bar">
|
|
<div class="top-bar-left">
|
|
<a class="back-link" onclick="showToast('返回目录页')">
|
|
<span class="back-arrow">←</span><span>返回</span>
|
|
</a>
|
|
<span class="top-bar-index">009 / 047</span>
|
|
</div>
|
|
<div class="top-bar-right">看不清的事情</div>
|
|
</header>
|
|
|
|
<!-- 进度条 -->
|
|
<div class="progress-bar" id="progressBar"></div>
|
|
|
|
<!-- 文章元信息 -->
|
|
<div class="article-meta reveal">
|
|
<div class="article-category"><span>资料归档</span></div>
|
|
<div class="article-info">
|
|
<span class="info-item">录入 <strong>2025.03.17</strong></span>
|
|
<span class="info-dot"></span>
|
|
<span class="info-item">修订 <strong>2025.04.02</strong></span>
|
|
<span class="info-dot"></span>
|
|
<span class="info-item">阅读约 <strong>8 分钟</strong></span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Markdown 正文 -->
|
|
<article class="article-body-wrap">
|
|
<div class="md" id="articleContent"></div>
|
|
<div class="article-end"><span class="end-mark"></span></div>
|
|
</article>
|
|
|
|
<!-- 上下篇 -->
|
|
<nav class="article-nav">
|
|
<div class="nav-card prev" onclick="showToast('前往上一篇:雨后积水倒影的几点笔记')">
|
|
<div class="nav-card-label">← 上一篇</div>
|
|
<div class="nav-card-title">雨后积水倒影的几点笔记</div>
|
|
<div class="nav-card-arrow">←</div>
|
|
</div>
|
|
<div class="nav-card next" onclick="showToast('前往下一篇:地铁报站语音的语调变化')">
|
|
<div class="nav-card-label">下一篇 →</div>
|
|
<div class="nav-card-title">地铁报站语音的语调变化</div>
|
|
<div class="nav-card-arrow">→</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<!-- 页脚 -->
|
|
<footer class="site-footer">
|
|
<span>看不清的事情 · 009</span>
|
|
<span>UNCLEAR MATTERS</span>
|
|
</footer>
|
|
|
|
<!-- Toast -->
|
|
<div class="toast" id="toast"></div>
|
|
|
|
<script>
|
|
// Markdown 原文
|
|
const articleMd = `# 窗户反光中偶见的现象
|
|
|
|
关于玻璃表面映像的几点观察,及一些可能并不相关的联想。
|
|
|
|
---
|
|
|
|
## 一、关于时间
|
|
|
|
反光中的景象与窗外实际的景象之间存在时间差——当然不是物理意义上的,而是注意力意义上的。当你注意到反光时,真正的事物已经发生了微小的偏移:云的位置变了,树影的角度变了,某个人已经走过了那个路口。反光中的世界似乎总是慢半拍,像是一则被延迟转播的新闻。
|
|
|
|
我在连续七天的同一时刻(下午三点)记录了同一扇窗户的反光。第三天和第五天的映像几乎一致——同样的灰色天空,同样的对面楼顶水塔轮廓——以至于我一度怀疑自己是否记错了日期。但仔细对比,水塔阴影的方向有大约两度的差异。这让我意识到,反光记录的不是「画面」,而是光线经过的路径。画面可以重复,路径不会。
|
|
|
|
> 玻璃不生产影像,它只是允许光线通过或将其遣返。我们看到的「反光」,其实是被拒绝的光。
|
|
|
|
## 二、关于重叠
|
|
|
|
最令我着迷的是反光与透射的重叠时刻。黄昏时分,室内灯光未开,室外的天光正在减弱——这个时候,玻璃同时呈现两种画面:
|
|
|
|
- 反射回来的室内物体轮廓
|
|
- 透过玻璃可见的室外景观
|
|
|
|
它们不融合,而是共存在同一个平面上,像两张幻灯片叠在一起。
|
|
|
|
### 技术记录
|
|
|
|
| 时间 | 天气 | 可辨识层数 |
|
|
|------|------|-----------|
|
|
| 17:30 | 阴 | 1 |
|
|
| 17:45 | 阴转多云 | 2 |
|
|
| 18:00 | 多云 | 2 |
|
|
| 18:15 | 微雨 | 3 |
|
|
| 18:30 | 雨 | 1 |
|
|
|
|
这种现象在技术上有明确的解释,与光强比例和玻璃的反射率有关。但我感兴趣的并不是解释本身,而是那种视觉上的**不确定性**——当你的目光在两种画面之间来回切换时,你会短暂地失去判断:这个轮廓属于室内还是室外?那条线是窗框还是对面楼的边缘?
|
|
|
|
有几次,我在这种重叠中看到了不属于任何一侧的东西。比如一个模糊的人形轮廓,既不像室内的人,也不像窗外路过的行人。理性告诉我这是角度和距离造成的视觉误差——两具不同来源的映像恰好拼合成了一个可识别的形状。但那个瞬间确实存在,而且它看起来那么真实。
|
|
|
|
> 本条目不涉及任何超自然主张。上述观察均基于光学现象的日常表现,所谓「偶见」仅指观察时机的不确定性。
|
|
|
|
## 三、关于留意
|
|
|
|
后来我开始有意识地留意各种反光表面:
|
|
|
|
1. 电梯里的不锈钢面板
|
|
2. 雨后的汽车引擎盖
|
|
3. 手机屏幕待机时的黑色镜面
|
|
4. 深夜地铁车窗
|
|
|
|
它们各自呈现着不同的世界切片,有些清晰有些模糊,但共同点是:它们都不「属于」那个表面本身。
|
|
|
|
这让我想到一个也许不恰当的类比:我们所见的大部分事物,是否也像玻璃上的映像一样——我们看到的是经过折射、反射、延迟之后的版本,而非事物本身?这个问题太大了,不适合在这里展开。我只记录现象。
|
|
|
|
---
|
|
|
|
最后一条记录来自今早。刷牙时,洗手台上方有一面小镜子,镜子里映出身后浴室窗的玻璃,那扇玻璃上映着对面楼阳台上的晾衣绳。衣服在风中轻微摆动。我盯着看了大约十秒钟。然后光线的角度变了,映像消失了,玻璃重新变得透明,外面只有一片白茫茫的天。
|
|
|
|
我把这一刻记下来,仅仅因为它发生了。
|
|
|
|
*录入:2025.03.17 · 修订:2025.04.02*`;
|
|
|
|
// 渲染
|
|
marked.setOptions({ breaks: true, gfm: true });
|
|
document.getElementById('articleContent').innerHTML = marked.parse(articleMd);
|
|
|
|
// 首字下沉:给正文第一个 p 加样式
|
|
const firstP = document.querySelector('.md p');
|
|
if (firstP) {
|
|
const text = firstP.textContent;
|
|
if (text.length > 0) {
|
|
firstP.innerHTML = '<span class="drop-cap">' + text[0] + '</span>' + text.slice(1);
|
|
}
|
|
}
|
|
|
|
// 进度条
|
|
const progressBar = document.getElementById('progressBar');
|
|
window.addEventListener('scroll', () => {
|
|
const scrollTop = window.scrollY;
|
|
const docHeight = document.documentElement.scrollHeight - window.innerHeight;
|
|
if (docHeight <= 0) return;
|
|
progressBar.style.width = (scrollTop / docHeight * 100) + '%';
|
|
});
|
|
|
|
// 滚动显示
|
|
const revealElements = document.querySelectorAll('.reveal');
|
|
const revealObserver = new IntersectionObserver((entries) => {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) entry.target.classList.add('visible');
|
|
});
|
|
}, { threshold: 0.1, rootMargin: '0px 0px -30px 0px' });
|
|
revealElements.forEach(el => revealObserver.observe(el));
|
|
|
|
// Toast
|
|
let toastTimer;
|
|
function showToast(msg) {
|
|
const toast = document.getElementById('toast');
|
|
toast.textContent = msg;
|
|
toast.classList.add('show');
|
|
clearTimeout(toastTimer);
|
|
toastTimer = setTimeout(() => toast.classList.remove('show'), 2500);
|
|
}
|
|
</script>
|
|
|
|
<style>
|
|
/* 首字下沉 */
|
|
.drop-cap {
|
|
float: left;
|
|
font-size: 3.4em;
|
|
line-height: 1;
|
|
margin-right: 8px;
|
|
margin-top: 4px;
|
|
font-weight: 600;
|
|
color: #1a1a1a;
|
|
font-family: 'Noto Serif SC', serif;
|
|
}
|
|
</style>
|
|
|
|
</body>
|
|
</html> |