返回

文章详情

Gooey:一个为Zig加速的GPU UI框架

Hacker News2026年6月3日 17:12

Gooey是一个为Zig加速的GPU UI框架,支持macOS(Metal)、Linux(Vulkan/Wayland)和浏览器(WASM/WebGPU)。加入Gooey Discord讨论早期开发:API正在不断演化。使用Gooey构建的示例应用——chat-zig,一个使用Zig 0.16 std.Io堆栈进行异步HTTP的Anthropic Claude客户端: 功能特性: - GPU渲染——macOS上的Metal,Linux上的Vulkan,带MSAA抗锯齿(WebGPU/WASM在Zig 0.16上被阻止——请参见WASM) - 声明式UI——基于组件的布局,使用ui.*原语和Flexbox风格系统 - Cx/UI分离——Cx用于状态、处理程序和焦点;ui.*用于布局原语 - 纯状态模式——可测试的状态方法,具有自动重新渲染 - 动画系统——内置动画,支持缓动,animateOn触发 - 实体系统——动态实体创建/删除,自动清理 - 保留控件——TextInput、TextArea、Checkbox、滚动容器 - 文本渲染——CoreText(macOS)、FreeType/HarfBuzz(Linux)、Canvas(WASM) - 自定义着色器——可以插入自己的Metal/GLSL着色器 - 拖放——类型安全的拖动源和放置目标,支持pointer_events控制 - 液态玻璃——macOS 26.0+ Tahoe透明窗口效果 - 动作和键绑定——具有密钥映射的上下文动作系统 - 主题——内置的明暗模式支持 - 图像和SVG——加载图像,并使用样式呈现SVG图标 - 文件对话框——本地文件打开/保存对话框(macOS、Linux、WASM) - 剪贴板——在所有平台上支持本地剪贴板 - IME支持——支持国际文本输入的输入法编辑器 - 可访问性——内置屏幕阅读器支持(VoiceOver、Orca、ARIA),具有语义角色和实时区域 - 零依赖性——没有外部Zig包依赖;仅针对系统框架/库构建(Objective-C运行时绑定在树中加捆) 快速入门要求:Zig 0.16.0+ 依赖性:无。Gooey没有任何外部Zig包依赖——build.zig.zon列出了零依赖性。它仅针对平台系统框架/库链接(见下面的平台说明)。 macOS:macOS 12.0+ Linux:Wayland合成器,Vulkan驱动程序,FreeType,HarfBuzz,Fontconfig,libpng,D-Bus 示例命令: - zig build run # 展示演示 - zig build run-counter # 计数器示例 - zig build run-todo # 待办事项应用(状态、处理程序、TextInput、列表) - zig build run-animation # 动画演示 - zig build run-pomodoro # 番茄钟 - zig build run-glass # 液态玻璃效果 - zig build run-spaceship # 带着着色器的太空仪表板 - zig build run-dynamic-counters # 实体系统演示 - zig build run-layout # Flexbox、缩小、文本换行 - zig build run-actions # 键绑定演示 - zig build run-select # 下拉选择组件 - zig build run-tooltip # 工具提示组件 - zig build run-modal # 模态对话框 - zig build run-images # 图像加载和样式 - zig build run-file-dialog # 本地文件对话框 - zig build run-uniform-list # 虚拟列表(1万项) - zig build run-virtual-list # 变量高度列表 - zig build run-data-table # 虚拟表(1万行) - zig build run-code-editor # 带语法高亮的代码编辑器 - zig build test # 运行测试 示例:一个小的待办事项应用,涉及API的代表性切片:纯界面无关的状态模型;cx.update / cx.updateWith / cx.command处理程序;绑定的TextInput;Checkbox和Button;列表迭代;以及不涉及UI的状态测试。完整的可运行源代码位于src/examples/todo.zig(zig build run-todo)。其状态模型由底部显示的测试覆盖,这些测试作为zig build test的一部分运行。 ```zig const std = @import ( "std" ); const gooey = @import ( "gooey" ); const ui = gooey . ui ; const Cx = gooey . Cx ; const Button = gooey . components . Button ; const Checkbox = gooey . components . Checkbox ; const TextInput = gooey . components . TextInput ; const MAX_TODOS = 64 ; const TEXT_CAP = 128 ; const draft_input_id = "new-todo" ; // 状态是纯粹的 — 无UI知识,完全可测试。 const Todo = struct { buf : [ TEXT_CAP ] u8 = [ _ ] u8 { 0 } ** TEXT_CAP , len : usize = 0 , done : bool = false , fn text ( self : * const Todo ) [] const u8 { return self . buf [0 .. self . len ]; } }; const Filter = enum { all , active , done }; const AppState = struct { todos : [ MAX_TODOS ] Todo = [ _ ] Todo {.{}} ** MAX_TODOS , count : usize = 0 , draft : [] const u8 = "" , // 与TextInput双向绑定 filter : Filter = .all , // 纯逻辑 — 以下测试内容推动的函数。 fn pushTodo ( self : * AppState , value : [] const u8 ) void { const trimmed = std . mem . trim ( u8 , value , " \t \r \n " ); if ( trimmed . len == 0 ) return ; if ( self . count >= MAX_TODOS ) return ; const slot = & self . todos [ self . count ]; const n = @min ( trimmed . len , TEXT_CAP ); @memcpy ( slot . buf [0 .. n ], trimmed [0 .. n ]); slot . len = n ; slot . done = false ; self . count += 1 ; } pub fn toggle ( self : * AppState , index : usize ) void { if ( index >= self . count ) return ; self . todos [ index ]. done = ! self . todos [ index ]. done ; } pub fn remove ( self : * AppState , index : usize ) void { if ( index

赞助内容

NordVPN Next-gen Antivirus

本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。

请我喝杯咖啡