从零构建程序化风景生成器:Canvas 分形地形 + 一键投稿到华为云作品展览馆

举报
yd_293143657 发表于 2026/10/19 00:10:27 2026/10/19
【摘要】 用 Canvas 值噪声与 fbm 生成可复现的风景页面,再把封面、详情包、仓库和 STS 临时凭证串成一条投稿流水线,附接口契约与踩坑清单。

一、为什么要做程序化风景

手工做一张封面图要挑图、调色、切图,做十次就烦十次。风景这类画面又有很强的规律性:山脊的起伏、天空的渐变、雾气的浓度,本质上是几组参数决定的噪声函数。既然这样,不如把它写成一个函数——输入一个随机种子,输出一个可以独立部署的单文件页面。

最终产出的 index.html 是零依赖的:没有框架、没有构建、没有外链字体,双击就能打开,扔到任何静态托管上都能跑。这也是投展览馆时最省事的地方:详情包只需要说明与截图,源码直接走公开仓库。

二、地形:值噪声 + fbm 叠加

山体用四层轮廓分别生成,由远及近,振幅从 0.11 递增到 0.20,营造近大远小的纵深。每一层的顶点由一维值噪声采样得到,再做分形叠加(fbm):把频率翻倍、振幅减半,叠四层左右,锯齿就被抹成了自然的山脊线。

关键点是同一个种子必须得到同一帧。噪声的梯度表用种子洗牌初始化,后续所有随机数都从这条链上派生。只要记录下 seed、时辰、天气三个值,任何一台机器都能复现出完全一样的画面。

三、配色与天气:五时辰 × 六天气

时辰取 dawn / morning / noon / dusk / night,各有一套天空色、日月位置、山体明暗。天气取 clear / mist / clouds / rain / snow / aurora,控制云量、雾浓度、雨雪粒子数、星辰密度和极光带。

组合是加权取样而不是均匀随机:雨雪会压低权重,因为粒子会抢画面主体,做成封面不好看;晴、雾、云、极光才是主力。作品名用两组词库交叉组合,简介按时辰和天气从模板生成,再强制裁到 15~50 个字符——这是投稿接口的硬约束。

四、把作品投到开发者作品展览馆

页面做完只是第一步,真正费时间的是投稿链路。几个实测出来的关键点:

  1. 封面必须是 1280×720,而且要过字形校验。做法是把标题渲染到封面后,用一个像素密度检查脚本切一条横带,比较「有字区」和「控制区」的深色像素比例,比例不达标就说明字体没命中、中文渲染成了豆腐块。
  2. 简介长度按 Unicode 码点算,不是按汉字个数。中文一个字算 1,标点也算,超了直接 400。
  3. 上传体要压到 200KB 以内。原始 PNG 封面 813KB,在这个出口带宽下要传 50 秒以上,而网关读 body 大约 30 秒就断,客户端只看到 Broken pipe 或偶发 502。统一转成 JPEG(q88)后上传体降到 150KB 上下,12 秒左右传完,稳定成功。
  4. 详情 zip 有结构契约:根目录只能有一个 README.md,图片全部放 resources/ 下,单张不超过 5MB,整包不超过 20MB、条目数不超过 50。源码不放详情包,走 gitUrl。

投稿接口是 POST /open-api-public/v1/gallery/works,multipart 提交,身份靠三个头:X-Tmp-Ak、X-Tmp-Sk、X-Security-Token,另外要带一个 Idempotency-Key 防止重试造成重复作品。

五、临时凭证怎么来

接口只认最小权限的 STS 临时凭证,不认永久 AK/SK。正确姿势是用 KooCLI 现场换:hcloud STS AssumeAgency --cli-region=cn-north-4 --agency_urn=iam::<账号ID>:agency:<委托名> --agency_session_name=<会话名> --duration_seconds=900 --policy=<最小权限策略JSON>。

换出来的凭证只写进临时文件,用完立刻删,不落盘、不进 git。第一次跑很容易踩的坑是委托不存在,STS 直接报 STS5.1106——那就先在 IAM 里建一条同名委托,信任关系指向自己账号即可。

六、踩过的坑

  • 作品名同账号内不能重复,重名会失败,报错信息也不指向名字。
  • gitUrl 必须公开可达。塞一个不存在的地址,接口会返回「代码仓库地址无法访问」;私有仓库同样过不了。
  • 无头截图要注意时机。窗口固定 1280×720,同时用 virtual-time-budget 让动画先跑几帧,否则截到的是空白画布。
  • 端口占用。截图脚本会起一个临时 HTTP 服务,8099 被占就直接失败,换端口即可。

七、结果

按这套流程跑下来,两次投稿都一次通过,作品页可以直接访问,积分奖励 200 也同步到账。更有意思的是复用性:把生成器换个主题就是另一组作品,把投稿逻辑抽出来就是一条通用流水线——真正花时间的是接口契约和上传体积,而不是画面本身。

如果你也想做类似的东西,建议从「一个种子 → 一张图 → 一个单文件页面」这条最短路径开始,先让画面跑起来,再回头处理封面、详情包、仓库和凭证。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。