告白墙的便签往哪贴:网格找空隙、25% 重叠上限与满板 409

举报
yd_252071992 发表于 2026/11/07 08:31:40 2026/11/07
【摘要】 一张便利贴贴上墙,位置不能随便定:贴得太整齐像表格,贴得太随意又会把别人的告白盖住。我的告白墙项目里,新便签的落点由服务端一个专门的放置算法决定,规则就三条:找最空的地方、最多允许四分之一被盖住、实在没地方就明确告诉用户贴不下了。下面把这套规则拆开讲。一、先定容量:一块板 24 张,最多 5 块板展板不是无限大的。服务端给每块板定了一个硬上限:24 张。发布一条新告白时,服务端从用户当前正在...

一张便利贴贴上墙,位置不能随便定:贴得太整齐像表格,贴得太随意又会把别人的告白盖住。我的告白墙项目里,新便签的落点由服务端一个专门的放置算法决定,规则就三条:找最空的地方、最多允许四分之一被盖住、实在没地方就明确告诉用户贴不下了。下面把这套规则拆开讲。

一、先定容量:一块板 24 张,最多 5 块板

展板不是无限大的。服务端给每块板定了一个硬上限:24 张。发布一条新告白时,服务端从用户当前正在看的那块板开始,依次检查 5 块板:哪块板还没满、且能在上面找到空位,新告白就落在哪块;5 块板全满或者全都找不到空位,就返回 409,前端弹出空间不足的提示,而不是悄悄把新告白贴到别人上面。

这里有个容易误解的点:每板 24 张这个数是写死的,不是按视口尺寸算出来的。视口尺寸真正决定的是另一件事——在这块板上,网格能划出多少个格子、空隙出现在哪里。容量是固定数,落点才是按视口算的。

首次打开页面时,前端会先用一个很小的请求探一下现在一共有几块板,然后直接加载最后一块板——也就是最新的那块。这样用户一进来看到的就是最新内容,而不是从第一块板慢慢翻过去。

二、找空位:网格法,先找离别人最远的格子

放置算法的第一步是网格搜索。服务端拿到发布请求里带的视口宽高(发布那一刻的浏览器窗口尺寸),把展板划成格子:格子宽是便签宽的 0.85 倍,格子高是便签高的 0.85 倍。0.85 这个系数是故意的:格子比便签略小,相邻格子的便签会轻微交错,墙面看起来就不会像电子表格那样死板。

划格子时还要扣掉不能贴的区域:顶部留 55 像素给标题栏,底部留 30 像素给翻板用的页点,四周各留 10 像素边距。扣完之后,每个格子逐一检查是不是空的,空的格子都进候选名单。

候选不止一个时,算法挑离已有便签最远的那一个:对每个空格子,算它到所有已有便签中心距离的最小值,取最小值最大的那个。板子刚开始是空的,第一张便签没有“别人”可比,就直接落第一个格子。平局时加一个极小的随机扰动打破,避免每次都贴在同一个角落。

三、什么叫“空”:25% 重叠上限

“空”不是“完全没人贴”,而是“被盖住的部分不超过四分之一”。判断方法是采样:把候选位置的矩形划成 10×10 的采样网格,一共 100 个点,逐个检查落在已有便签范围内的点有几个;被盖住的点不超过 25 个,这个位置就算空。

这个 25% 的上限,是整面墙视觉效果的关键。要求零重叠,墙面利用率会很低,贴几张就“满”了;允许随便重叠,新贴的又会把旧内容盖得没法读。25% 的意思是:新便签至少有四分之三露在外面,旧便签被盖住一角也不至于读不出内容。这是一个折中值,不是算出来的最优解,是试出来的手感。

四、别太整齐:抖动与旋转角

格子法有个副作用:落点天然对齐。算法在选定格子后会再做最多 5 次抖动:横向和纵向各加一个不超过便签尺寸 7.5% 的随机偏移,偏移后的位置仍要满足 25% 的重叠约束才采用;5 次都通不过,就用格子原位。落定之后再给一个 -6° 到 +6° 之间的随机旋转角。

抖动和旋转都不影响“空”的判定——它们只在已确认为空的位置附近小幅调整。这样墙面看起来是随手贴上去的,但每张便签的可见面积仍然有保障。随意的观感是设计出来的,不是真的随机乱贴。

五、网格找不到,就随机投 500 次

板子贴得很满的时候,网格法可能一个空格子都找不出来。这时算法换第二招:随机投放。随机取一个位置,用同样的 25% 约束检查,最多试 500 次。500 次里只要有一次通过,就用那个位置;500 次全部失败,算法返回失败,服务端回 409。

500 次这个数字同样是手感:太少了,板子明明还有空位却报满了;太多了,一次发布请求要等很久。网格法已经处理了绝大多数情况,随机投放只是兜底,500 次足够覆盖那些网格对不齐的边角空位。

六、位置是数据:拖拽、置顶与移动端

便签贴上去之后还可以拖动。拖拽结束,前端把新坐标发给服务端保存,请求发出就不等回包——位置保存失败不会打断用户的拖动体验,下次刷新时以服务端存的位置为准。置顶用 z-index 表示:大于 1 就视为已置顶,渲染时按 z-index 排序,置顶的便签浮在上面。

这套位置逻辑只在桌面端成立。屏幕宽度小于等于 600 像素时,前端把便签改成流式纵向排列:位置、旋转、置顶按钮全部失效。手机屏幕上本来就没有“墙面”的概念,硬套桌面那套坐标没有意义,改成列表是最务实的选择。顺带一提,如果发布请求里没带视口尺寸,算法会退回一个固定落点,不会报错——发布流程的健壮性比位置的精致更重要。

结尾

这套放置规则没有用什么高深算法:网格找空隙、采样算重叠、随机做兜底。但它把三个容易含糊的问题都落成了明确的数:每板 24 张、重叠不超过 25%、随机投放 500 次封顶。做小项目时,这种“先定数、再写代码”的顺序很值得借鉴——约束先写清楚,算法只是在约束里面找答案;约束含糊,再聪明的算法也贴不出一面好看的墙。

演示地址(纯文本):https://gbq.515123.xyz

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

评论(0)

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

全部回复

上滑加载中

设置昵称

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

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

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