设为首页收藏本站喵玉殿官方微博

 找回密码
 少女注册中
搜索
查看: 298|回复: 13

为你的主页添加樱花特效🌸:基于自由模块脚本注入的Canvas渲染

[复制链接]
发表于 2026-7-19 14:55:14 | 显示全部楼层 |阅读模式
本帖最后由 Codishek2005 于 2026-7-20 00:01 编辑

通过论坛的自由模块,你可以为自己的喵玉殿个人主页添加酷炫的同款樱花特效,也可以执行其他任意脚本以实现各种功能(甚至完全渲染成另一个完全不同的页面)。接下来我们将深入此背后的机制,了解如何利用论坛的设计缺陷在浏览器上执行任意脚本。

自由模块:自由的脚本
在喵玉殿个人主页的装扮空间里存在这样一个功能:自由模块。这个模块可让你在里面编写任意文本,同时也包括HTML代码,在模块里编写的HTML代码会渲染到页面上。正是此特性使得实现执行脚本成为可能。

但此时就遇到了第一个困难:我们不能直接在模块里编写<script>。自由模块并非直接将里面的内容渲染到页面上,而是会进行一些预处理,其中包括将换行符替换为<br>标签、移除<script>标签。而要实现樱花特效,就需要依赖在页面上执行自定义代码创建Canvas,因此我们必须另辟蹊径。

Onload 是你所需要的一切
在HTML里有一个元素属性叫onload,它指定了当元素包含的资源完成加载、触发load事件时,所要执行的代码。

而正巧合的是,我偶然发现喵玉殿并不会移除掉此onload属性!

因此出现了一个思路,我们可以利用<img>图片元素。至于是什么图片无所谓,我们重点关心的是其onload属性,可以往onload里写入精心设计的脚本,以此来实现Canvas渲染。

因为图片展示的内容对我们不重要,所以最好是使用足够小的图片,搭配CSS属性display: none以避免图片元素干扰其他内容。为了尽可能减小加载图片带来的影响,我们可以使用Data URL(本质上是将文件内容转换为一种特殊的链接)直接嵌入图片到HTML代码中,以此来免去网络加载图像的开销。

现在我们构建了一个极限小的单像素GIF图像,使用Data URL编码:
data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7

然而接下来还有第二关......

字数限制:自由的边界
有一次我在模块里测试各种各样的脚本,发现有时候脚本会不工作。最终发现是模块有字数限制,我粘贴进去的脚本全部被截断了。

这可不妙,仅靠1000字的代码可没法实现完整的樱花飘落动效,更何况前面的<img>元素就已经耗掉了约100字。即使有可能通过各种奇技淫巧使用剩下900字实现樱花飘落,我们也不打算去探讨怎么实现,毕竟现在讨论的主题可不是 IOCCC其实就是我菜

同源策略与CORS
既然我们没法靠900字的空间来编写代码,那么就需要找出一种方式能足够容纳所有的代码。一部分人或许觉得可以将脚本随便扔到GitHub之类的地方然后再去引用,但实际上这条路行不通,因为这跟接下来提到的同源策略(Same-Origin Policy)有关。

现代浏览器为了安全,引入了同源策略机制。在默认情况下浏览器会阻止跨域脚本请求,而GitHub并没有显式设置CORS请求头,意味着你无法从喵玉殿请求位于GitHub上的资源。当然,我们可以找一个同源策略限制宽松的托管网站,或者也可以自己搭建网站并允许从喵玉殿访问。但如果我告诉你,其实喵玉殿相册就能存储脚本呢?

图像之外
现在有一张特殊的图像,如果直接打开看的话会发现是一片空白。

但如果你用16进制编辑器来看的话,就会发现里面的蹊跷:

而这正是利用了论坛对图像校验的机制!

当你从论坛相册上传图片时,论坛会校验图片是否为允许的文件类型,以及能否正常加载,这意味着你上传一堆垃圾数据会失败。同时相册上传的文件大小限制是500KiB,超出这个限额之后也会失败。

绝大多数主流的图像格式,都会有一个结束标识来告诉图像解码器“图像已经完成加载”。在大部分解码器实现里,通常读取到这个标识就停止解析了。对于PNG图像,这个结束标识是IEND块:

而恰巧的是,论坛也不在乎PNG IEND块之后的数据!只要是可正常读取的图片,并且不超过大小上限,在IEND块之后无论填充什么数据都能正常上传。

到此,我们已经有了一个完整的设计思路了。先将完整的樱花动效代码存储在图片尾部,然后在主页的自由模块里编写加载器用于请求图像文件,截获图像尾部之后的代码并执行。对于樱花动效的代码,500KiB空间绰绰有余;对于自由模块的加载器,1000字也足够用。

为了节省流量,图像尾部的脚本还可以跑一遍GZIP压缩。在自由模块加载器代码里使用现代浏览器的DecompressionStream API去解压GZIP数据流,而这部分解压的代码塞进1000字里也正好足够。

樱花飘落🌸
现在,我们已经有了在个人主页上执行任意代码的能力,接下来的一切都好办了。

我们通过脚本在<body>最后添加一个<canvas>元素,在Canvas里面绘制樱花花瓣,这样樱花飘落的画面就会叠加到整个页面上(确保你的绘制上下文启用了Alpha)。

花瓣绘制
要绘制樱花花瓣,我们可以通过两个三次贝塞尔曲线来拟合,其中一个绘制左半部分,另一个是右半部分。

此处是我摸索出的观感比较好的坐标参数:

飘落动效
为每一片花瓣分配随机的移动速度、转速、横向摆动频率,在requestAnimationFrame()里每一帧更新位置、角度并重绘,即可让花瓣动起来。

不要忘记Delta Time,这是在不同设备上保持相同速度观感的关键!

尾声:互联网安全的启示
尽管现代浏览器在安全机制上采用了严格的限制,但也只能减少一部分网站上的用户生成内容的威胁。在服务端层面上,服务端始终不应该信任用户的每一个输入。

也许这部分的内容会在论坛架构发生改变后不适用,也有可能一直保持现状,谁又知道未来是怎样的呢?

灵感来源
其实我一开始都不知道个人主页还有自由模块,直到我看到了 常荣棉 (UID:273332) 的个人主页,才开始细究原理。

程序员的直觉告诉我,这头像能转起来肯定有蹊跷(笑)

评分

参与人数 3积分 +1 喵玉币 +30 萌度 +85 收起 理由
RoadSa + 10 + 30
9654 + 10 + 30 辛苦
常荣棉 + 1 + 10 + 25

查看全部评分

发表于 2026-7-19 15:08:19 | 显示全部楼层
连这个都看不懂,我完蛋了()
回复

使用道具 举报

发表于 2026-7-19 15:19:46 | 显示全部楼层
看起来好强的样子……可惜了我不懂代码(
回复

使用道具 举报

发表于 2026-7-19 16:35:57 | 显示全部楼层
好厉害,我觉得您应该把这篇文帖子投到技术馆,要是放在水区没多久就会被其它帖子淹了

点评

技术馆人太少了(  发表于 2026-7-19 16:49
回复 1 0

使用道具 举报

发表于 2026-7-19 16:41:26 | 显示全部楼层
sdl,tql.   
回复

使用道具 举报

发表于 2026-7-19 17:01:04 | 显示全部楼层
本帖最后由 常荣棉 于 2026-7-19 17:10 编辑

居然是看到我的主页吗(惊讶)
个人主页我推荐看 @Ahhaha233 的,他的fumo动画更好看一点()至于原理……我用的是css选择器,我猜他也是用的这个?

以及: @moi 学会了吗


点评

确实是用 css 选择器  发表于 2026-7-20 16:13
回复

使用道具 举报

发表于 2026-7-19 19:05:23 | 显示全部楼层
本帖最后由 麻薯一个罢了 于 2026-7-19 19:08 编辑

学习一波,争取撒两把纸钱()

点评

是吗()  发表于 2026-7-19 22:37
这个已经不属于html了()  发表于 2026-7-19 21:50
后续:html从入门到放弃()  发表于 2026-7-19 19:52
回复

使用道具 举报

发表于 2026-7-19 22:08:50 | 显示全部楼层
豆包豆包帮我一键生成
回复

使用道具 举报

发表于 2026-7-20 16:11:08 | 显示全部楼层
666
之前在 onload 里写过东西但没什么用,这下可以整活了
感谢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 少女注册中

本版积分规则

合作与事务联系|无图版|手机版|小黑屋|喵玉殿

GMT+8, 2026-8-7 02:58

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表