简介面向UI设计师与产品经理这份《全球国旗图标集》汇集了260多个国家与地区的矢量国旗素材以Sketch格式呈现可直接用于移动应用、网站界面、地理信息系统、国际会议展示等场景免去逐个绘制的重复劳动。压缩包大小约89.05MB内含Sketch源文件及配套说明文档同时提供circle、pin、hexagon、square、rectangle等不同形态的子文件方便按地图标记、按钮图标、布局元素等需求快速取用。已有1840人学习下载尤其适合需要全球化视觉资源的中高级设计师。得益于统一的设计风格与完整的国家覆盖图标集既能保证项目视觉一致性也能显著缩短多语言、多地区的设计交付周期配合Read Me中的授权与使用说明可以在合法合规的前提下高效落地到实际产品中。1. 为什么 260 多个国旗要放进一套 Sketch 素材里做海外业务的时候最麻烦的不是接口联调而是每个语言版本都要有一套看着“不破”的国旗。临时去各家图库下载有的偏色、有的格式不统一放大到 2x 就发虚文件名还经常和锚点文本对不上。这个素材包把 260 多个国家的国旗做成了 Sketch 矢量符号并按 circle、pin、hexagon、square、rectangle 五种形态分别归档。它解决的不只是“有没有国旗”而是“把一串国旗放进同一套设计系统时依然整齐”。适合 UI 设计师维护国际化组件库也适合前端工程师拿导出资源做语言切换、地图大屏和支付区域选择。下面的章节按拆包、命名、导出、排错、校验这条线把这个包用透。2. 拆包素材目录结构、Symbol 命名与形态选型2.1 先看 zip 内部清单再决定注册哪些库收到压缩包后我习惯先从命令行看内容而不是双击解压。这样可以根据Read Me.html判断授权也可以在导入 Sketch 之前确认文件是否完整。列目录的命令很简单unzip -l Global_Flags_Kit.zip | head -40能看到circle/、pin/、hexagon/、square/、rectangle/五个目录。如果只想确认某个具体国家在不在用unzip -l Global_Flags_Kit.zip | grep -E circle/(cn|us|gb|de)如果压缩包较大也可以换成zipinfo -1只输出文件名。这一步能帮你提前发现文件缺失或文件名乱码避免导入 Sketch 后才发现某个洲整组丢失。这五个目录的差异不是美术风格而是裁剪区域和视觉用途。我一般会给设计团队列一张选型表避免同一个国旗在语言选择器和地图上用错形态目录图形形态典型 UI 场景circle圆形裁切语言切换下拉框、用户头像、地图 POIpin图钉/水滴形地图大屏、物流轨迹、目的地选择hexagon六边形边框数据仪表盘、科技感按钮、主题徽章square正方形国家列表、设置页项、卡片缩略图rectangle横向矩形表格首列、结算页国家选择、Banner 头部结构上讲这是把同一个国旗源图形复制成五个父级组再各自打上不同的裁剪遮罩不是五份原始描边。好处是你在任意一个形态里改国旗颜色其余形态并不会同步但如果结构里用了 Shared Style调整主色时所有形态都会联动。这也是后面做团队模板时要明确的要的是“共享色值”还是“共享路径”。2.2 读 Read Me确认授权和版本约束压缩包里的Read Me.html不是装饰文档。macOS 上可以用open打开Windows 直接双击也行但内容里经常写明默认 Symbol 命名、适用 Sketch 版本号、商用限制。一个更快的检索方式grep -iE license|授权|commercial|version Read Me.html如果作者贴了 MIT 或 CC那么你可以直接把它接进团队 Library。如果只写了“个人使用”就不要进商业提交流程。这块后文第 4 章还会讲到。2.3 Sketch Symbol 命名分层与团队复用真正的可复用性来自 Sketch 的 Symbol 机制。打开载入库后插入菜单里会看到flags/circle/cn、flags/rectangle/de这种带/的层级名称。Sketch 把/前面的部分当作分组命名规范可以总结成三层类型/形态/ISO 代码。例如flags/pin/r u表示俄罗斯国旗的 pin 形态 Symbol。这里有个关键约定第三层必须用 ISO 3166-1 alpha-2 的小写代码不要写中文、不要写Russian否则前端压根没法对文件路径。在 Sketch 中管理这套符号时我一般会把这些 Symbol 统一放进一个独立 Symbols Page然后通过 Preferences Libraries 把这个文件添加为 Library。这样项目文件里的每个国旗实例都保持与源文件同步后续想加新国家或修正某个国旗颜色全团队只要重新同步一次。需要调整某个国旗细节时一定要从库中复制 Symbol 再改名。直接右键点击 master symbol 进入隔离编辑确实快但会把原始库文件改掉应用中其他人那边立刻变样。团队的规范是master 不动要改先复制。3. 从 Sketch 到前端批量导出与国旗命名管线3.1 用 sketchtool 批量导出而不是手工点切片设计稿验收之后最耗时的步骤是把两百多个国旗从 Sketch 里一张张导出。手工导出不仅容易漏命名还会有“xx副本”。常见做法是用 Sketch 官方命令行工具sketchtool导出 slices。官方 sketchtool 对 slices 支持最稳你可以在每个国旗 Symbol 上套一个同名 Slice。然后执行sketchtool export slices ./Global_Flags.sketch \ --output./export \ --scales1,2,3 \ --formatspng参数含义--scales1,2,3会同时生成 1x、2x、3x 三套倍率--formatspng输出 PNG也可以同时写png,webp具体取决于版本--output指定导出根目录。导出后的文件路径默认保持 slice 名称层级也就是export/flags/circle/cn2x.png这样的结构前端不用再做一轮重映射。如果你的 sketchtool 版本支持export symbols可以更直接sketchtool export symbols ./Global_Flags.sketch \ --symbol-name-prefixflags/ \ --output./export \ --scales2--symbol-name-prefix会只导出名称以flags/开头的符号避免把无关控件一起导出去。旧版本没有这个参数退回到 slices 方案即可。如果整个素材包里没有 Slice 层也可以在 Sketch 里全选国旗组使用 “Make Exportable” 批量设置 2x 导出。这个操作的启动成本很低但会产生 260 多个 export 集合我一般只在拿不到 sketchtool 的 Windows 机器上才会让设计师这样处理。3.2 用 ISO 代码统一国旗文件名与内联加载导出命名最好直接用小写 alpha-2 国家代码而不是中文或英文。否则前端的 mapping 表会非常难维护。我自己在项目里维护的映射规则大致是这样规范代码出现在文件里的别名说明gbuk、eng、uk-eng英国在体育场景常写作 ukkrko、kor、south-korea韩国在 i18n 里经常写成 kocnzhongguo、china中文场景下容易出中文名在前端代码里直接拼接路径比写死一张地图更省事。假设导出文件都在/assets/flags/shape/code.png可以这样封装export function getFlagUrl(countryCode, shape circle) { const code countryCode.trim().toLowerCase(); return /assets/flags/${shape}/${code}.png; } const aliases { UK: gb, ENGLAND: gb, KO: kr, KOR: kr, CHN: cn, }; export function normalizeFlagCode(input) { const key String(input || ).trim().toUpperCase(); return (aliases[key] || key.slice(0, 2)).toLowerCase(); }上面getFlagUrl只是字符串拼接不负责把非法代码变成有效地址所以要在路由层先用normalizeFlagCode做一次清洁。aliases里保存真实业务中会出现的非标准代码不至于让ko变成kr的 bug 在线上反复出现。需要按需加载时直接在组件里这样用const FlagImage ({ countryCode, shape circle }) { const url getFlagUrl(normalizeFlagCode(countryCode), shape); return img src{url} width{24} height{24} alt{countryCode} /; };这样写的好处是新增国家只需要新增 PNG前端不需要重新发版。若你的打包器支持动态import也可以把国旗资源通过 CDN 独立存放走import(/* webpackIgnore: true */ url)模式避免把 500 多张图一次性打进 bundle。3.3 批量为导出结果生成索引两百多个文件交付时要检查有没有破图可以加一个生成manifest.json的 Node 脚本。核心逻辑只有 20 行const fs require(fs); const path require(path); const ROOT path.resolve(__dirname, export); function walk(dir) { return fs.readdirSync(dir, { withFileTypes: true }).flatMap((entry) { const full path.join(dir, entry.name); return entry.isDirectory() ? walk(full) : [full]; }); } const manifest walk(ROOT) .filter((file) file.endsWith(.png)) .map((file) file.replace(ROOT path.sep, ).replace(/\\/g, /)); fs.writeFileSync(path.join(ROOT, manifest.json), JSON.stringify(manifest, null, 2));manifest.json会列出全部导出资源前端可以用它做Mapstring, url的预加载池。执行前确保export目录存在如果文件夹被清空脚本只输出一个空数组所以最好在 CI 里再校验数组长度。4. 解压失败、Sketch 版本和色彩还原的边界4.1 zip 解压报错与修复的通用排查拿到压缩包后第一个碰到的坑通常在解压环节。error read zip archive这句话很常见原因是下载不完整、文件名编码不符或安全软件拦截。不要急着找“修复工具”先做三件事用unzip -t测试完整性。用 7-Zip 单独解压避免 Windows 自带解压对中文文件名的兼容问题。对比下载大小与发布页标注的字节数。如果确实压缩文件本身出了问题可以做有限修复unzip -t Global_Flags_Kit.zip zip -FF broken.zip --out fix.zip 7z x fix.zip -oC:/workspace/flagszip -FF尝试修复损坏的压缩文件头7z x作为兼容性更好的解压工具。这两个命令不是“密码破解”也不能恢复被截断的文件所以核心还是确认网络下载没丢字节。这里要专门提醒如果压缩包加密提示输入密码只能找源作者要口令不要使用任何所谓的“密码移除”工具。加密的 zip 素材通常是分发方版权控制硬解并不能规避授权问题。4.2 Sketch 版本不兼容与库的同步问题这个素材包如果是新近整理的很可能用较新的 Sketch 版本保存。老版本打开会出现“无法打开文稿”或提示“文件由较新版本的 Sketch 创建”。Sketch 没有向下兼容的“另存为旧版”选项遇到这种情况我一般按下面顺序处理先看Read Me.html里是否写了最低版本要求再让素材提供方在安装 Sketch 的机器上用匹配版本重新保存一次如果团队统一用老版本可以把.sketch导入 Figma 转出 SVG再存回本地素材库或者直接把五个目录重新制作为 Library路径不变。这里要特别提醒Sketch Library 的全量同步是基于 symbolID 的如果你把素材包里的 master 复制到自己的库却改过 symbolID原有实例不会自动更新。因此不建议在库文件里删除 system symbol 再重建。4.3 国旗色彩还原与交付前的权限核对Sketch 素材里的国旗颜色一般接近标准但显示器、打印分色和前端色彩管理会带来偏差。比如英国国旗的蓝色标准值接近#012169某些素材包可能写成#003399中国国旗的红常被简化为#EE1C25实际项目如果需要严格还原建议从权威来源核对 Pantone 值。国旗关键色常用 HEX中国红#EE1C25法国蓝#0055A4英国深蓝#012169德国金#FFCC00颜色问题看似小事但一旦多个部门共用 Library不同屏幕贴图出来就会有色差。给关键色建 Shared Style锁定在团队模板里比每次从国旗里取色更稳定。授权方面要记得Read Me.html写明的是个人学习还是商业授权。国旗作为国家象征不属于普通版权素材商用前需要确认使用场景不构成对国家形象的扭曲。交付清单里最好附一张授权来源表记录素材包名称、下载页、license 摘要避免两年后换版权联系人时拿不出证据。5. 用 ISO 3166 校验国旗素材完整性的脚本最后一个技巧是把“确认 260 多个国家是否都齐”这个人工活变成脚本。由于.sketch文件本身是 zip页面文件都是 JSON所以完全可以用 Python 直接读。import json import re import zipfile def collect_symbol_names(sketch_path): names set() with zipfile.ZipFile(sketch_path) as zf: for member in zf.namelist(): if member.startswith(pages/) and member.endswith(.json): page json.loads(zf.read(member)) def walk(node): if not isinstance(node, dict): return names.add(node.get(name, )) for layer in node.get(layers, []) or []: walk(layer) walk(page) return names def find_flag_codes(names): codes set() for name in names: # 匹配 flags/circle/cn 这种三层写法 m re.fullmatch(rflags/(?:circle|pin|hexagon|square|rectangle)/([a-z]{2}), name) if m: codes.add(m.group(1)) return codes official_codes {cn, us, gb, de, fr, jp, kr, ru, in, br, it, es} codes_in_sketch find_flag_codes(collect_symbol_names(Global_Flags.sketch)) missing official_codes - codes_in_sketch extra codes_in_sketch - official_codes print(missing:, sorted(missing)) print(extra:, sorted(extra))逻辑说明collect_symbol_names遍历pages/*.json里所有层的name属性find_flag_codes用正则在符号名里抓flags/形态/两位代码。official_codes是 ISO 3166-1 alpha-2 的“必须存在”集合建议直接用pycountry生成import pycountry official_codes {c.alpha_2.lower() for c in pycountry.countries}需要留意的是Sketch 文件中同名符号可能出现多次用set去重。如果源文件把gb写成了uk脚本会把它归入extra同时missing中出现gb这时候需要人工确认 aliases 是否存在而不是直接补文件。把这段逻辑接进 CI 的 pre-publish 钩子里出图前自动跑一遍能省掉至少两轮人工改稿。本文还有配套的精品资源点击获取