一、3×3 分区在做什么
- 四个角(1/3/7/9):完全不缩放。圆角、边框装饰、高光都在这里,保护它们就是九宫格的全部意义。
- 四条边(2/4/6/8):单轴拉伸。左右两条只改高度,上下两条只改宽度——所以边框粗细恒定。
- 中心(5):双轴拉伸。可以关掉(Unity 的 Fill Center、CSS 里不画中间),做中空框时常用。
二、哪些能切,哪些绝对不能切
容器九切,图标缩放。有边框、中间是纯色或规则纹理的(面板、对话框、按钮、提示框、血条/进度条、输入框)→ 九切;有具体形象的(道具图标、logo、角色头像、插画)→ 只能等比缩放,九切会把它的中间拉变形,越看越不对。
拿不准时问自己一个问题:这张图的中间区域,被拉宽两倍之后还成立吗?纯色底板成立,一张脸不成立。
三、四边内边距怎么量
内边距(inset)就是四条分割线的位置,量错整个九切就废了。规则:
- 必须完整包住角饰:圆角、描边转角、角上的装饰花纹,全部要在角区里。切到花纹中间,拉伸时花纹会断。
- 中间要留够可拉伸区:工程上常要求至少 8px。中间区太小(比如只剩 2px),拉伸时会出现可见的接缝或摩尔纹。
- 能被 4 整除:UI 尺寸惯例(纹理压缩与对齐友好),常见做法是让整张图四边内边距都取偶数。九宫格源图工程规范里通常要求 ≤ 256×256,够用即可,不要拿 1024 的图去切。
- 内边距往里收,别往外扩:切到角饰就往里挪;只有确认中间还剩足够空间时,才往外放。
四、各引擎怎么设
Unity(uGUI)
- 贴图导入设置:
Texture Type = Sprite (2D and UI),保持单张 Sprite。 - 打开 Sprite Editor,填四个边框值
L / R / T / B(像素),Apply。 - 给 Image 组件赋值,
Image Type = Sliced;需要中空就关掉Fill Center。 - 改大小时改 RectTransform 的 Width / Height,不要改 Transform 的 Scale——Scale 是整体缩放,会把你辛苦保护的圆角一起放大。
Godot
用 NinePatchRect 节点,贴图上设 Patch Margin(Left / Top / Right / Bottom)。按钮的常态、悬停、按下三态要用 Theme 里的 StyleBoxTexture 分别配,不要只改一张图的颜色。
Android(.9.png / Nine-patch)
在 PNG 四周各留 1px 画黑线:左边和上边的黑线标"可拉伸区",右边和下边的黑线标"内容区"(文字能放进去的范围)。必须是 .9.png 结尾,且黑线只能是纯黑(#00000000 之外的纯黑),差一个色值 Android 就不认。
CSS
用 border-image:border-image-source 指定图,border-image-slice 填内边距(可带 fill 保留中心),并配一个对应的 border-width。
五、几个一踩就废的坑
- 用 Scale 代替改尺寸:整体缩放会绕过九切,四角照样变形。改尺寸,不改缩放。
- 开了 Trim(自动裁透明边):图集打包时如果自动裁掉透明边,九切内边距的坐标基准就变了,边框会歪。九切素材的 Trim 要关掉。
- mipmap 导致缩小后发虚:九切区域被缩到比源图小的时候,渲染会取低级别 mipmap,边框变糊。做法是要么关掉 mipmap,要么让源图本身就处在"只会被放大"的尺寸区间。
- 图集里相邻串图:图集打包时相邻格子之间必须留 padding(常见 2px),且九切素材建议单独放一张图集,别和图标混排。
- 奇数尺寸 + 半像素:UI 尺寸尽量取偶数、能被 4 整除,否则在高 DPI 屏上容易出现 1px 边缘发虚。
六、帧工坊里怎么走这一步
九切本身在引擎里完成,但素材准备可以在这里做:先把 AI 出的面板图去背、把边缘脏色修掉,再按需要的档位导出(九切源图不用大,够用即可),最后检查体积。
常见问题
九切之后还要导出 @2x/@3x 吗?
要,但只需一两档。九切解决的是"同一档下适配不同尺寸",解决不了"不同 DPI 屏的清晰度"。常见做法是出 @2x(主档)和 @3x(高清档),九切内边距按各自档位换算(2 倍图的边距也是 2 倍)。
为什么我设了九切,拉伸后圆角还是变形?
九成是用 Scale 缩放而不是改尺寸,或者内边距切进了圆角内部(角区没有完整包住圆角)。先检查这两项。
中心区域可以斜着铺图案吗?
斜纹、带方向的纹理拉伸后会露馅(纹理被拉长)。中心区最好是纯色、渐变或无方向性的规则纹理;实在要花纹,考虑让中心改成平铺(tile)而不是拉伸。
血条 / 进度条怎么做?
外壳(带边框的那层)做九切,填充层用单独一张可平铺或可裁剪的图,靠代码改填充比例。别把填充层也九切——它的长度是连续变化的。