Pixerate 畫布
畫布是一個 xyflow (React Flow / SvelteFlow) 圖形:一個由節點和邊組成的陣列。
一個節點是 { id, type, position: { x, y }, width?, height?, parentId?, zIndex?, data };邊是
{ id, source, target, label? }。所有設計功能知道的資訊都存在 node.data 中,因此在複製、貼上和 JSON 時都能保留:
data.label/data.name:文字內容和圖層名稱。data.shape:一個形狀節點 ({ kind: rect | ellipse | polygon | star | path, fill, stroke, strokeWidth, ... })。data.layout:一個自動佈局框架(modehorizontal / vertical / grid,gap,padding,alignMain,alignCross,sizing);其子節點是parentId為該框架的節點,順序為節點陣列順序。data.childLayout:子節點的尺寸設定(fixed / hug / fill)和約束。data.component(一個主要元件),data.componentSet(一組變體),data.instance({ componentId, properties })以及data.componentOverrides。data.locked、data.animation(關鍵影格軌道)、data.tokenBindings(設計代碼)。
位置以畫布(流程)單位表示;子節點的位置相對於其父節點。節點 ID 來自 get_editor_state;元件和集合 ID 來自 list_components。接受 ids 或 id 的工具,當您省略時,預設會使用目前的選取,因此,除非您剛剛使用 canvas_select 選取,否則請明確傳遞 ID。請參閱 pixerate-agent-tools 以了解命名空間、run_commands 批次處理和錯誤代碼。
工作流程技能
對於這些工作,請同時載入工作流程技能:它包含了方法、步驟之間的檢查和陷阱,並使用以下工具。
pixerate-canvas-design-system-components:元件、實例、變體集合和覆寫。pixerate-canvas-layout:對齊、分佈、排序和鎖定。
工作方法
- 讀取。 使用
includeDocument: false的get_editor_state回傳canvas.nodes和canvas.edges。對於設計系統,也要呼叫list_components,並在變更實例前呼叫inspect_instance。 - 先規劃結構:哪些框架、哪些可重複使用的元件和變體、什麼 間距比例。先建立一次主要元件,然後放置實例;不要手動複製節點。
- 寫入。 使用專用工具進行圖形編輯(
canvas_add_node、canvas_connect、canvas_update_node)和元件編輯(create_component、create_instance、...)。使用 設有atomic: true的run_commands來執行排列、形狀和動畫命令,以及在任何需要將 多個步驟視為一個復原步驟時使用(參數"$0.ids[0]"會使用先前步驟回傳的 ID)。 - 整理。 對圖形使用
canvas_layout;對設計使用canvas.align*/canvas.distribute*; 使用canvas.bringToFront等命令調整圖層順序;使用canvas.lock鎖定完成的背景。 - 查看。 批次完成後使用
view_editor(預設檢視區、JPEG、1024 像素);對整個繪圖使用scope: "canvas"。修正重疊、未對齊和文字裁切問題,然後使用canvas_select或canvas_highlight向使用者顯示。
與使用者並肩工作(他們正在建立,而您未經要求地添加):建議而非編輯。propose_nodes 會顯示使用者可以接受或取消的幽靈節點,在此之前,不會有任何內容到達畫布或其歷史記錄。保持每個提議小而集中於一個想法(一個標題、系列中的下一張卡片、一個遺失的連接器),為其提供一個 title 和一句話的 rationale,並使用 nearNodeId 將其錨定在它所補充的節點上。除非使用者要求,否則永遠不要接受自己的提議。使用 reject_proposal 撤回過時的提議:當使用者變更了提議所依據的內容時,list_proposals 會在其下顯示為 missing。
最佳實踐
-
設計系統思維。 任何出現兩次的東西都應該是一個元件:建立一個主要元件, 使用
combine_as_variants處理狀態和尺寸(例如State=Default,State=Hover,Size=Small),然後 在每個地方使用create_instance。變更主要元件以變更所有實例;僅對每個使用情況的內容(標籤文字、圖示切換)使用覆寫。一致地命名變體屬性和值(屬性使用 Title Case,值簡短),並保持組合唯一。 -
使用穩定的
data.name來命名必須在變體切換後保留的圖層。 比對會退回到data.label,而對於文字,其內容在不同的變體之間會有所不同。 -
使用元件屬性,不要分離。 使用
set_instance_properties切換變體並設定文字或布林 屬性;使用swap_instance切換到另一個元件。僅當實例必須停止跟隨其主元件時才分離。 -
間距比例。 選擇一個基礎單位(4 或 8)並使用其倍數作為間距和內邊距。將行 和堆疊放入自動佈局框架(
data.layout)中,而不是手動定位子節點,這樣當內容變更時,它們會自動重新排列。 -
對齊和分佈。 對齊到共享的邊緣或中心,然後以相等的間距進行分佈; 當邊緣對齊時,設計看起來井然有序。鎖定您想要作為錨點的節點:鎖定的節點永遠不會移動,但仍計入選取範圍。
-
圖層。 背景在後,內容在中間,疊加層在最上方。使用重新堆疊命令;它們會設定每個兄弟群組的
zIndex,並且永遠不會重新排序陣列。 -
圖形佈局。 將流程以一個方向佈局(管線用
LR,階層用TB), 保持邊短,僅在關係不明顯時為邊添加標籤。 -
動態效果。 對於進入的元素使用緩慢結束(或使用
ease-out-back產生輕微反彈), 離開的元素使用緩慢開始,在兩個靜止位置之間移動時使用緩慢進出,對於持續運動(例如旋轉)僅使用linear。將 UI 轉場保持在 150 到 400 毫秒左右,進入時間保持在 600 毫秒以下;使用delay將相關元素錯開 30 到 80 毫秒,而不是讓所有東西同時移動。對opacity、x、y、scale和rotation設定動畫;色彩補間在 OKLab 色彩空間中進行插值。 -
筆觸繪製。 當使用者想要手繪外觀(素描、墨水、鉛筆、麥克筆)時使用筆刷;保持普通筆觸用於圖表和 UI。沿曲線每隔 2 到 8 個畫布單位發送點,並使用短的
pressure輪廓(漸細的末端:[0.2, 0.9, 1, 0.9, 0.2])而不是使用許多不同寬度的點來塑造線條形狀。省略width以 使用預設集自己的尺寸(canvas.listBrushes會提供);僅在需要讓標記更細或更粗時才傳遞它。 -
筆刷特性。 每個預設集都有其自己的繪製特性:炭筆和粉彩寬且帶有顆粒感(它們會抓住紙張的紋理), 蠟筆和粉筆也是如此;鉛筆細膩且略有顆粒感;墨水、麥克筆、筆刷筆、原子筆、凝膠筆和細線筆是乾淨的(細線筆保持一種寬度),噴槍是一種柔和的噴霧。顆粒感和抖動是根據每個筆觸進行種子設定的,因此筆觸看起來總是相同,相鄰的筆觸共享同一張紙。為了外觀選擇筆刷,然後是顏色;對於素描,使用一或兩種筆刷,而不是全部使用。具有預設顏色的筆刷(原子筆藍色、螢光筆黃色、粉筆)在您不傳遞
color時會以該顏色繪製;傳遞color以使用另一種顏色。淺色/深色預設值(粉筆)會根據畫布的色彩配置解析(canvas.setColorScheme;主機通常會比對其主題)。 -
為人設定筆,而不是繪製。
canvas.selectBrush選擇使用者手動繪製時使用的筆刷,就像筆刷選擇器一樣:它會使用筆刷的預設顏色,除非使用者鎖定了他們的顏色(canvas.setColorLocked, "Keep my colour")或者您傳遞了keepColour。以這種方式取得的預設會遵循配置,直到設定了其他顏色。尊重使用者設定的鎖定;不要解鎖它來變更他們的顏色。這些是編輯器狀態,不是復原步驟,並且不會影響canvas.drawFreehand,後者使用自己的brush和color。 -
使用手勢進行註釋,而不是點。 以設計師標記印刷品的方式標記作品, 使用手勢命令(
canvas.circle、canvas.underline、canvas.arrow、canvas.bracket、canvas.strike、canvas.cross、canvas.check)並搭配節點 ID ({ "nodeId": "..." })或方塊,而不是計算出canvas.drawFreehand的點。一個 呼叫會繪製一個手繪標記。當您在談論畫布上的某個東西時,註釋會有所幫助:圈出揀選的項目,在重要的行下劃線,從色板畫一個箭頭到其使用位置,用括號括起您正在描述的群組,劃掉或 打叉一個被拒絕的選項,打勾一個已批准的選項。當畫布上沒有正在被參考的東西時,請跳過它,並且每個觀點只保留幾個標記:一張佈滿標記的頁面無法傳達任何訊息。 -
手勢風格。 一個審閱回合使用一種顏色(紅色或強烈的藍色筆在大多數設計上看起來像標記),僅對圓圈和底線使用螢光筆,並且如果您希望它們看起來像手繪,一個回合的每個標記都使用相同的
brush(marker或ink-pen)。標記是根據其請求進行種子設定的,因此再次要求會繪製相同的標記;傳遞另一個seed以獲得不同的效果。當標記需要文字時,在括號旁邊或箭頭尾部放置一個邊緣註記(一個文字節點)。
工具參考
讀取
| 工具 | 用途 |
|---|---|
get_editor_state | 讀取畫布圖形(canvas.nodes、canvas.edges),並且預設也會讀取提示文件。在僅畫布的任務中傳遞 includeDocument: false 以保持結果較小,includeCanvas: false 則僅讀取提示。在一開始以及使用者進行編輯後再次呼叫它。 |
view_editor | 取得編輯器的圖像:scope viewport(預設)或 canvas(整個繪圖的邊界),format jpeg(預設)或 png,maxEdge 以像素為單位(預設 1024)。在批次後使用它來判斷重疊、平衡和可讀性;代理游標會被排除在外。 |
capture_view | 截取畫布的一部分以檢查結果:region viewport(預設,與螢幕上相同)、content(每個節點)、selection、nodes(使用來自 get_editor_state 的 ids)或 rect(畫布單位);padding(預設 16)、maxEdge(預設 1024)、format png(預設)或 jpeg。結果會提供被截取的 rect 和 scale,因此影像像素(px, py)對應於畫布點(rect.x + px / scale, rect.y + py / scale)。偏好使用 nodes 以最高細節檢查您剛剛添加的內容。除非 includeOverlays,否則選擇框和代理游標會被排除在外。 |
list_components | 列出主要元件(id、name、變體值、實例計數)以及具有其變體選項的元件集合。在 create_instance、swap_instance 或任何變體工具之前呼叫它,以獲取 ID 和確切的屬性名稱和值。 |
inspect_instance | 描述一個實例(或其內部的圖層;預設為第一個選取的節點):其主元件、變體、具有類型的元件屬性值,以及每個圖層的覆寫。在 set_instance_properties 或 reset_overrides 之前呼叫它,以便使用正確的屬性名稱和覆寫群組。 |
寫入:圖形
| 工具 | 用途 |
|---|---|
canvas_add_node | 新增一個節點:node(id 可選且必須未被使用,type 由主機註冊,data、position、width、height、框架的 parentId)。省略 position 以自動放置在 nearNodeId 的 side(預設 right)旁邊而不重疊,這也會從該節點連接一條邊,或放置在最後一個節點旁邊。回傳新的節點 ID 和邊 ID。 |
canvas_connect | 從 source 到 target(兩個不同的現有節點)新增一條邊,可選 label。回傳邊 ID。 |
canvas_update_node | 將欄位合併到節點的 data 中(例如 { "label": "Checkout" })。將合併視為淺合併:完整傳遞巢狀物件,例如 shape 或 layout。它不會移動或調整節點大小。 |
canvas_remove_nodes | 刪除節點及其邊;每個 ID 必須存在。具有破壞性:在移除使用者製作的內容之前,請先與使用者確認。 |
canvas_layout | 自動排列圖形:direction LR(預設)、TB、RL 或 BT。incremental(預設為 true)保留已經有位置的節點;傳遞 false 以重新佈局所有內容。座標正好在 (0, 0) 的節點被視為未放置。 |
canvas_select | 取代選取(一個空列表會清除選取)。使用它來向使用者顯示結果,以及針對作用於選取的命令。 |
canvas_highlight | 閃爍節點以引導使用者注意它們:color(預設 #3b82f6)、durationMs(預設 2000,最大 60000)。不會變更任何內容。 |
展開和摺疊
具有可展開節點(一個可以打開成子任務的任務,一個甘特條形圖可以展開成其步驟)的主機會添加這些。 展開會顯示節點的子節點並移動周圍的節點以騰出空間;摺疊會移除子節點並將移走的節點放回原位。這是一個檢視變更,不是編輯:它不是一個復原步驟,也不會隨文件儲存。主機決定子節點是什麼。
| 工具 | 用途 |
|---|---|
list_explodable_nodes | 列出可以展開的節點(id、label、exploded、collapsing),當前 exploded 和 collapsing 的 ID,是否可以同時打開多個(multiple),以及如果展開被停用時的 readOnly 原因。首先呼叫它:它是可展開 ID 的唯一來源。 |
explode_node | 展開 node(來自 list_explodable_nodes 的 ID)。除非 multiple,否則之前展開的節點會摺疊(它會以 collapsed 狀態返回)。展開一個已經展開的節點不會有任何變更(changed: false)。回傳現在 exploded 的 ID。然後使用 get_editor_state 或 capture_view 來讀取或查看子節點。 |
collapse_node | 摺疊一個已展開的 node。回傳仍然 exploded 的 ID 和仍然 collapsing 的 ID(它們的子節點會在摺疊動畫結束時離開)。當節點未展開時會失敗。 |
提案(建議,不要編輯)
允許代理建議新增內容的主機會添加這些。一個提案是以幽靈形式顯示的新節點和邊(不可拖曳、選取或儲存)。
接受會將其作為一個復原步驟添加,記錄為由提出者(agent:<id>)所為;拒絕不會影響畫布及其歷史記錄。
| 工具 | 用途 |
|---|---|
propose_nodes | 提出要新增到畫布的節點和邊:nodes 和 edges(與 canvas_add_node / canvas_connect 接受的格式相同)、title、一個 rationale(一句話,為什麼)。可選:nearNodeId(提案錨定的節點;移動該節點會使提案過時)、parentId(提案的父框架,如果用於自動佈局框架則隱含一個最後的子位置)。回傳一個 proposalId。 |
list_proposals | 尚未處理的提案:每個提案都有 id、title 和 |
rationale,如果錨點 nearNodeId 已被移動或刪除,則為 missing: true。 | |
accept_proposal | 將提案及其所有節點和邊作為一個復原步驟提交到畫布。棄用其他提案。傳遞 ids 以僅接受多節點提案的一部分(僅接受那些節點)。需要先 inspect_proposal 以知道哪些 ids 是可接受的。 |
reject_proposal | 拒絕提案;它不會到達畫布。 |
inspect_proposal | 取得提案的詳細資訊:title、rationale、 |
nearNodeId、parentId、接受的 ids 以及接受的節點 "won't fit" 時的 | |
error。只有在您打算 accept_proposal 一部分時才需要。 |
批次(run_commands)
對於排列、形狀、動畫命令,以及任何您希望多個步驟在一個復原步驟中的時候,請使用 run_commands。接受一個 commands 陣列({ tool, params })和一個可選的 atomic 布林值(預設 true)。在所有命令都成功時提交一個復原步驟;否則回滾任何副作用並回報第一個錯誤。命令可以引用先前步驟回傳的值:格式 "$<stepIndex>.responsePath" 會用該值替換字串。
範例:
[
{ "tool": "canvas_add_node", "params": { "node": { "type": "text", "data": { "label": "Hi" } } } },
{ "tool": "canvas_add_node", "params": { "node": { "type": "text", "data": { "label": "There" } }, "nearNodeId": "$0.id" } }
]
並非所有工具都支援原子批次。不支援的工具會失敗。capture_view、view_editor、get_editor_state、list_*、inspect_*、view_editor 和 canvas_select 是無狀態的,永遠不會成為復原步驟的一部分,可以自由地與 canvas_add_node 等工具交錯使用。
寫入:形狀
形狀命令會寫入節點的 data.shape。它們可以作用於選取的節點,或者您也可以傳遞 nodeId。預設形狀是 stroke 和 fill 的 rect。路徑使用 SVG 路徑語法。
| 工具 | 用途 |
|---|---|
canvas.set_shape | 設定一個形狀。 |
canvas.flip | 水平或垂直翻轉。 |
canvas.rotate | 旋轉 90° 增量。 |
canvas.unite | 將選取的形狀合併為一個路徑。 |
canvas.subtract | 從底部形狀減去頂部形狀的路徑。 |
canvas.intersect | 僅保留形狀重疊的區域。 |
canvas.exclude | 移除重疊的區域。 |
canvas.offset_path | 沿其輪廓偏移一個路徑。 |
canvas.outline_stroke | 將筆觸轉換為填充的路徑。 |
canvas.flatten | 將向量圖層(形狀、文字、圖像)合併為一個形狀。 |
寫入:排列
這些命令作用於選取的節點,除非傳遞 ids。鎖定的節點會被計算在內但不會移動。
| 工具 | 用途 |
|---|---|
canvas.alignLeft / canvas.alignRight | 向左 / 向右對齊所選節點的邊緣。 |
canvas.alignTop / canvas.alignBottom | 向頂部 / 底部對齊。 |
canvas.alignCenterX / canvas.alignCenterY | 水平 / 垂直居中所選節點。 |
canvas.distributeHorizontal / canvas.distributeVertical | 均勻分佈水平 / 垂直間距。 |
canvas.bringToFront / canvas.bringForward | 將節點帶到圖層順序的最前面 / 向前一層。 |
canvas.sendToBack / canvas.sendBackward | 將節點送到圖層順序的最後面 / 向後一層。 |
canvas.lock / canvas.unlock | 鎖定 / 解鎖選取的節點。鎖定的節點不能移動,但圖層命令會計入它們。 |
寫入:繪圖
| 工具 | 用途 |
|---|---|
canvas.drawFreehand | 用一個筆觸繪圖:points 是 { x, y } 或 { x, y, pressure } 的陣列,brush(預設 "marker"),color(預設筆刷的顏色),width(可選,覆寫預設集)。壓力曲線比許多不同寬度的點產生更自然的結果。 |
canvas.drawPath | 從 SVG 路徑繪製一個形狀:d(路徑字串)、brush、color、width。 |
canvas.listBrushes | 列出可用的筆刷以及它們的預設顏色。 |
canvas.selectBrush | 為使用者的手動繪圖設定活動筆刷。傳遞 brush 以及可選的 keepColour(如果使用者鎖定了他們的顏色,則保留該顏色)。不是一個復原步驟。 |
寫入:手勢
| 工具 | 用途 |
|---|---|
canvas.circle | 在一個節點(nodeId)或一個矩形(rect)周圍畫一個手繪圓圈。brush(預設 "marker")和 color(預設紅色 "#e11d48")。 |
canvas.underline | 在一個節點或矩形下方畫一條底線。 |
canvas.arrow | 從一個節點或點畫一個箭頭到另一個節點或點。 |
canvas.bracket | 在一個節點或矩形周圍畫一個手繪括號。可選 side(left、right、top、bottom)。 |
canvas.strike | 在一個節點或矩形上畫一條刪除線。 |
canvas.cross | 在一個節點或矩形上畫一個叉號。 |
canvas.check | 在一個節點或矩形上畫一個勾選標記。 |
寫入:元件
| 工具 | 用途 |
|---|---|
create_component | 從選取的節點建立一個(主要)元件。回傳元件 ID。 |
create_instance | 從一個元件建立一個實例。傳遞 componentId 和可選的 overrides、position。回傳實例 ID。 |
add_variant | 在元件上建立一個變體。傳遞 componentId、name(變體名稱)、values(屬性 -> 值對映,例如 { "State": "Hover" })。回傳變體 ID。 |
combine_as_variants | 將多個元件組合成一個變體集合。傳遞 componentIds 和 property(變體屬性名稱)。 |
set_instance_properties | 在一個實例上設定屬性。傳遞 instanceId 和 properties(屬性 -> 值對映)。 |
swap_instance | 將一個實例的元件交換為另一個。傳遞 instanceId 和 newComponentId。 |
reset_overrides | 重置一個實例上的所有覆寫。 |
list_property_definitions | 列出一個元件或變體集合上定義的屬性。 |
寫入:佈局
| 工具 | 用途 |
|---|---|
canvas.set_layout | 在一個節點上設定自動佈局框架。傳遞 nodeId 和 layout(mode、gap、padding 等)。 |
canvas.set_child_layout | 設定一個子節點在其自動佈局父框架中的尺寸設定和約束。傳遞 nodeId 和 childLayout(sizing、constraints)。 |
canvas.set_constraints | 設定一個節點的自訂約束(最小/最大寬度/高度)。 |
寫入:動畫
| 工具 | 用途 |
|---|---|
canvas.add_keyframe | 添加一個關鍵影格:nodeId、property(例如 opacity、x、y)、time(秒)、value、easing(可選)。 |
canvas.set_animation | 設定一個節點的完整動畫(一個關鍵影格陣列)。 |
canvas.export_css | 為選取的內容或整個畫布導出動畫為 CSS。 |
其他
| 工具 | 用途 |
|---|---|
canvas.setColorScheme | 設定畫布的色彩配置(light / dark)。不是一個復原步驟。 |
canvas.undo | 復原最後一個復原步驟。 |
canvas.redo | 重做最後一個復原步驟。 |