chore: 初始化项目仓库
This commit is contained in:
commit
17a224be27
8 files changed
+690
No files matched your search
@@ -0,0 +1,115 @@
|
||||
@font-face {
|
||||
font-family: "Zpix";
|
||||
src: url("../fonts/zpix.ttf") format("truetype");
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100dvh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
font-family: "Zpix", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei",
|
||||
"Noto Sans SC", "Source Han Sans SC", sans-serif;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
/* 28 列 × 44 行文字网格,1em = 1 个汉字;
|
||||
字号在这里统一控制,所有元素(含天线)字号完全一致 */
|
||||
.scene {
|
||||
position: relative;
|
||||
font-size: min(3.4vw, calc(100dvh / 44));
|
||||
line-height: 1em;
|
||||
width: 28em;
|
||||
height: 44em;
|
||||
user-select: none;
|
||||
font-kerning: none;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: block;
|
||||
height: 1em;
|
||||
line-height: 1em;
|
||||
white-space: pre;
|
||||
/* Zpix 单字步进为 13/12 em,补偿回 1em,保证 28 列正好落在 28em 内 */
|
||||
letter-spacing: -0.083333em;
|
||||
}
|
||||
|
||||
/* —— 标题区:按整格扣出的黑色矩形,左右各留 3 格 —— */
|
||||
.title-panel {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.title-panel .title {
|
||||
margin: 0;
|
||||
color: #fff;
|
||||
font-size: 1.6em;
|
||||
font-weight: 400;
|
||||
line-height: 1;
|
||||
letter-spacing: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* —— 背景:空白格里的淡色「天」 —— */
|
||||
.sky { color: rgba(190, 200, 240, 0.15); }
|
||||
|
||||
/* —— 云:固定颜色,明度取太阳与黑底之间的一半,色相沿用晚霞色 —— */
|
||||
.cloud { color: color-mix(in srgb, var(--cloud, #ff9ebb) 35%, #000); }
|
||||
.cloud-pink { --cloud: #ff9ebb; }
|
||||
.cloud-violet { --cloud: #b98cff; }
|
||||
.cloud-orange { --cloud: #ffa95c; }
|
||||
.cloud-rose { --cloud: #ff85b3; }
|
||||
.cloud-lilac { --cloud: #c98cff; }
|
||||
|
||||
/* —— 落日:太阳逐行色调,t1 顶部偏红 → t17 底部偏黄;整体明度为原色的 90% —— */
|
||||
.sun { color: color-mix(in srgb, var(--tone, #ff5a36) 90%, #000); }
|
||||
.sun-t1 { --tone: #ff5a36; }
|
||||
.sun-t2 { --tone: #ff5a36; }
|
||||
.sun-t3 { --tone: #ff6533; }
|
||||
.sun-t4 { --tone: #ff7330; }
|
||||
.sun-t5 { --tone: #ff812d; }
|
||||
.sun-t6 { --tone: #ff8f2b; }
|
||||
.sun-t7 { --tone: #ff9d29; }
|
||||
.sun-t8 { --tone: #ffaa2a; }
|
||||
.sun-t9 { --tone: #ffb62d; }
|
||||
.sun-t10 { --tone: #ffc132; }
|
||||
.sun-t11 { --tone: #ffcb38; }
|
||||
.sun-t12 { --tone: #ffd33f; }
|
||||
.sun-t13 { --tone: #ffda46; }
|
||||
.sun-t14 { --tone: #ffe04e; }
|
||||
.sun-t15 { --tone: #ffe556; }
|
||||
.sun-t16 { --tone: #ffe95e; }
|
||||
.sun-t17 { --tone: #ffec66; }
|
||||
|
||||
/* —— 飞鸟 —— */
|
||||
.bird-sparrow { color: #e0a45c; }
|
||||
.bird-gull { color: #a0c8f0; }
|
||||
.bird-crow { color: #b0a8c8; }
|
||||
|
||||
/* —— 天线 —— */
|
||||
.ant { color: #8a8a9e; }
|
||||
|
||||
/* —— 楼群:灰色系,明度与原棕色一致 —— */
|
||||
.bld { color: #3f3f3f; }
|
||||
.bld-1 { color: #3b3b3b; }
|
||||
.bld-2 { color: #343434; }
|
||||
.bld-3 { color: #464646; }
|
||||
.bld-4 { color: #393939; }
|
||||
.bld-5 { color: #4e4e4e; }
|
||||
.bld-6 { color: #414141; }
|
||||
.bld-7 { color: #494949; }
|
||||
.bld-8 { color: #353535; }
|
||||
Binary file not shown.
@@ -0,0 +1,160 @@
|
||||
/* 落日文字画 · 28 × 44 网格
|
||||
构图全部由下方数组描述;空白格自动用「天」铺满。
|
||||
修改元素只需调整数组中的坐标与尺寸,行列范围:x 0–27,y 0–43。 */
|
||||
|
||||
(() => {
|
||||
const COLS = 28;
|
||||
const ROWS = 44;
|
||||
|
||||
/* 云:x/y 为最宽一行的左上角,三行 3/5/3;上下拉开分布 */
|
||||
const clouds = [
|
||||
{ x: 10, y: 2, tone: 'pink' },
|
||||
{ x: 18, y: 6, tone: 'violet' },
|
||||
{ x: 1, y: 10, tone: 'orange' },
|
||||
{ x: 23, y: 13, tone: 'lilac' },
|
||||
{ x: 4, y: 16, tone: 'rose' },
|
||||
];
|
||||
|
||||
/* 落日:整体下移贴近楼群,形成日落;
|
||||
色调按数组顺序,顶部偏红 → 底部偏黄 */
|
||||
const sun = [
|
||||
{ y: 18, x: 13, w: 2 },
|
||||
{ y: 19, x: 10, w: 8 },
|
||||
{ y: 20, x: 9, w: 10 },
|
||||
{ y: 21, x: 8, w: 12 },
|
||||
{ y: 22, x: 7, w: 14 },
|
||||
{ y: 23, x: 7, w: 14 },
|
||||
{ y: 24, x: 6, w: 16 },
|
||||
{ y: 25, x: 6, w: 16 },
|
||||
{ y: 26, x: 6, w: 16 },
|
||||
{ y: 27, x: 6, w: 16 },
|
||||
{ y: 28, x: 6, w: 16 },
|
||||
{ y: 29, x: 7, w: 14 },
|
||||
{ y: 30, x: 7, w: 14 },
|
||||
{ y: 31, x: 8, w: 12 },
|
||||
{ y: 32, x: 9, w: 10 },
|
||||
{ y: 33, x: 10, w: 8 },
|
||||
{ y: 34, x: 13, w: 2 },
|
||||
];
|
||||
|
||||
/* 飞鸟:数量减少,间距不等,仅少量成对;上下拉开分布 */
|
||||
const birds = [
|
||||
{ x: 0, y: 2, kind: 'gull' },
|
||||
{ x: 26, y: 2, kind: 'gull' },
|
||||
{ x: 1, y: 4, kind: 'sparrow' },
|
||||
{ x: 3, y: 8, kind: 'crow' },
|
||||
{ x: 6, y: 13, kind: 'gull' },
|
||||
{ x: 9, y: 15, kind: 'sparrow' },
|
||||
{ x: 26, y: 5, kind: 'crow' },
|
||||
{ x: 17, y: 9, kind: 'sparrow' },
|
||||
{ x: 21, y: 12, kind: 'gull' },
|
||||
{ x: 19, y: 15, kind: 'crow' },
|
||||
];
|
||||
|
||||
/* 天线:单列「线」,从 y 向下叠 h 格;楼顶在第 31 行,露出部分为 3 / 4 格 */
|
||||
const antennas = [
|
||||
{ x: 7, y: 28, h: 3 },
|
||||
{ x: 22, y: 27, h: 4 },
|
||||
];
|
||||
|
||||
/* 楼群:n 对应 .bld-n,最终按 x/y/w/h 铺满「楼」(高度裁到第 44 行) */
|
||||
const buildings = [
|
||||
{ n: 1, x: 0, y: 35, w: 3, h: 9 },
|
||||
{ n: 2, x: 3, y: 39, w: 3, h: 5 },
|
||||
{ n: 3, x: 6, y: 31, w: 4, h: 13 },
|
||||
{ n: 4, x: 10, y: 36, w: 3, h: 8 },
|
||||
{ n: 5, x: 13, y: 30, w: 4, h: 14 },
|
||||
{ n: 6, x: 17, y: 34, w: 3, h: 10 },
|
||||
{ n: 7, x: 20, y: 31, w: 4, h: 13 },
|
||||
{ n: 8, x: 24, y: 37, w: 4, h: 7 },
|
||||
];
|
||||
|
||||
/* 标题区:整格扣出的居中矩形,左右各留 3 格 */
|
||||
const TITLE = {
|
||||
text: '关于「甲子」的虚构故事',
|
||||
top: 14,
|
||||
height: 5,
|
||||
side: 3,
|
||||
};
|
||||
|
||||
const BIRD_WORDS = { sparrow: '麻雀', gull: '海鸥', crow: '乌鸦' };
|
||||
|
||||
const grid = Array.from({ length: ROWS }, () =>
|
||||
Array.from({ length: COLS }, () => ({ ch: '天', cls: 'sky' }))
|
||||
);
|
||||
|
||||
const put = (x, y, ch, cls) => {
|
||||
if (x < 0 || x >= COLS || y < 0 || y >= ROWS) {
|
||||
throw new Error(`元素超出网格范围:(${x}, ${y})`);
|
||||
}
|
||||
grid[y][x] = { ch, cls };
|
||||
};
|
||||
|
||||
const putRow = (y, x, n, ch, cls) => {
|
||||
for (let i = 0; i < n; i++) put(x + i, y, ch, cls);
|
||||
};
|
||||
|
||||
for (const { x, y, tone } of clouds) {
|
||||
const cls = `cloud cloud-${tone}`;
|
||||
putRow(y, x + 1, 3, '云', cls);
|
||||
putRow(y + 1, x, 5, '云', cls);
|
||||
putRow(y + 2, x + 1, 3, '云', cls);
|
||||
}
|
||||
|
||||
sun.forEach(({ y, x, w }, i) => {
|
||||
const tone = `sun-t${i + 1}`;
|
||||
for (let dx = 0; dx < w; dx++) put(x + dx, y, '日', `sun ${tone}`);
|
||||
});
|
||||
|
||||
for (const { x, y, kind } of birds) {
|
||||
const [a, b] = BIRD_WORDS[kind];
|
||||
put(x, y, a, `bird-${kind}`);
|
||||
put(x + 1, y, b, `bird-${kind}`);
|
||||
}
|
||||
|
||||
for (const { x, y, h } of antennas) {
|
||||
for (let i = 0; i < h; i++) put(x, y + i, '线', 'ant');
|
||||
}
|
||||
|
||||
for (const { n, x, y, w, h } of buildings) {
|
||||
for (let j = 0; j < h; j++) putRow(y + j, x, w, '楼', `bld bld-${n}`);
|
||||
}
|
||||
|
||||
for (let y = TITLE.top; y < TITLE.top + TITLE.height; y++) {
|
||||
for (let x = TITLE.side; x < COLS - TITLE.side; x++) {
|
||||
grid[y][x] = { ch: ' ', cls: 'cut' };
|
||||
}
|
||||
}
|
||||
|
||||
/* 把同 class 的连续字符合并成一个 span,减少 DOM 节点 */
|
||||
const html = grid
|
||||
.map((row) => {
|
||||
let line = '';
|
||||
for (let i = 0; i < COLS; ) {
|
||||
let j = i + 1;
|
||||
while (j < COLS && row[j].cls === row[i].cls) j++;
|
||||
const text = row.slice(i, j).map((cell) => cell.ch).join('');
|
||||
line += `<span class="${row[i].cls}">${text}</span>`;
|
||||
i = j;
|
||||
}
|
||||
return `<div class="line">${line}</div>`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
const scene = document.querySelector('.scene');
|
||||
scene.innerHTML = html;
|
||||
|
||||
const panel = document.createElement('div');
|
||||
panel.className = 'title-panel';
|
||||
panel.style.top = `${TITLE.top}em`;
|
||||
panel.style.left = `${TITLE.side}em`;
|
||||
panel.style.width = `${COLS - TITLE.side * 2}em`;
|
||||
panel.style.height = `${TITLE.height}em`;
|
||||
|
||||
const title = document.createElement('h1');
|
||||
title.className = 'title';
|
||||
title.textContent = TITLE.text;
|
||||
|
||||
panel.append(title);
|
||||
scene.append(panel);
|
||||
})();
|
||||
Reference in new issue
Block a user