把此刻,题成一张老照片。
一个纯前端的「老照片题字」工具:上传一张照片,自动生成带年代感的题字成品——照片的拍摄时间会被译成中文纪年(如「二零二六年正月」),拍摄地点会从 GPS 坐标里辨认出来,用毛笔体题在红幅或白边上,像极了抽屉底翻出来的那张老照片。
- 两种款式
- 红幅标语:照片满幅 + 深红横幅 + 米白毛笔字(上/下款可切换)
- 白边题字:暖白相纸 + 手书题字 + 朱文「留念」印章
- 横图竖图自适应,横幅/留白比例按画面自动调整
- 自动题字
- 读取 EXIF 拍摄日期 → 中文纪年「二零二六年正月」
- 读取 GPS → 逆地理编码(国内走高德,未配 key 走 OSM Nominatim)→ 自动补「拍摄于××」
- 没有定位信息时留待手填,所有文字均可自由修改
- 多行题字:换行即新一行,所有行统一字号
- 四种题字字体:行书 / 仿宋 / 宋体 / 手写,按钮即用对应字体显示,所见即所得
- 大图预览:点击照片查看原分辨率大图
- 原画质导出:最高 4096px,JPEG 下载
- 隐私:照片只在本机浏览器处理,不上传任何服务器
- Vite + React 19 + TypeScript
- exifr:EXIF 日期 / GPS 解析
- Canvas 2D:相纸、横幅、题字、印章合成
- 逆地理编码:高德 Web 服务(国内直连,坐标已本地转 GCJ-02)/ OSM Nominatim(免 key,海外或有代理时),按是否配置
VITE_AMAP_KEY自动选择,8 秒超时兜底 - 字体:马善政毛笔体 / 龙藏体 / Noto Serif SC(Google Fonts);仿宋用系统字(macOS 华文仿宋 / Windows 仿宋)
npm install
npm run dev # 开发调试
npm run build # 打包到 dist/
npm run preview # 本地预览打包产物
npm run lint # oxlint 检查逆地理编码默认走 OSM Nominatim(免费免 key,但国内网络多不可达)。配置高德 key 后改走高德 Web 服务,国内手机/电脑均可直连:
-
到高德开放平台注册(免费),创建应用并添加一个 Web 服务类型的 key;
-
本地开发:在项目根目录新建
.env.local(已被 git 忽略):VITE_AMAP_KEY=你的key -
重新
npm run dev/npm run build即可;未配置时自动回退 Nominatim,行为不变。
key 会打进前端产物(纯前端应用不可避免),可在高德控制台设置每日配额上限防止被盗用。坐标在本地转成 GCJ-02 火星坐标后再请求,定位无偏移。
项目为多阶段构建(容器内打包 + nginx 托管),服务器无需安装 Node:
docker build -t pic-synth . # 无高德 key(回退 Nominatim)
docker build --build-arg VITE_AMAP_KEY=你的key -t pic-synth . # 注入高德 key(推荐国内)
docker run -d --name pic-synth -p 80:80 --restart unless-stopped pic-synth构建上下文里有
.env.local时会自动沿用其中的 key,无需重复传参。
或使用 compose:
docker compose up -d --build # 无高德 key
VITE_AMAP_KEY=你的key docker compose up -d --build # 注入高德 keynginx.conf 已包含 SPA 回退、静态资源长缓存与 gzip 配置。
src/
├── lib/
│ ├── chineseDate.ts # 日期 → 中文纪年(一九九八年三月 / 二零二六年正月)
│ ├── photo.ts # EXIF 解析 + Nominatim 逆地理编码
│ └── render.ts # Canvas 合成:红幅标语 / 白边题字、题字排版、印章
├── App.tsx # 单屏编辑器:上传、题字、预览、导出
└── index.css # 暗房暖棕 + 旧相纸视觉