$npx -y skills add ZhangHanDong/makepad-skills --skill makepad-2.0-vectorCRITICAL: Use for Makepad 2.0 Vector graphics widget. Triggers on: makepad vector, Vector widget, SVG path, makepad path, makepad circle, makepad gradient, makepad tween, vector animation, Gradient, RadGradient, Filter, DropShadow, Group transform, vector drawing, inline SVG, 矢量图
| 1 | # Makepad 2.0 Vector Graphics Skill |
| 2 | |
| 3 | > **Version:** makepad-widgets (dev branch) | **Last Updated:** 2026-03-03 |
| 4 | |
| 5 | ## Overview |
| 6 | |
| 7 | The `Vector` widget renders resolution-independent vector graphics using SVG-like syntax. It supports paths, shapes, gradients, filters, groups, transforms, and property animation via `Tween`. |
| 8 | |
| 9 | **Two ways to use SVG in Splash:** |
| 10 | - **`Vector{}`** - Define shapes inline in Splash (paths, rects, circles, etc.) |
| 11 | - **`Svg{}`** - Load external `.svg` files via `crate_resource()` or `http_resource()`, with optional animation and custom GPU shaders |
| 12 | |
| 13 | ## Documentation |
| 14 | |
| 15 | Refer to the local files for detailed documentation: |
| 16 | - `./references/vector-reference.md` - Complete Vector API, shapes, gradients, filters, animation |
| 17 | |
| 18 | --- |
| 19 | |
| 20 | ## Basic Usage |
| 21 | |
| 22 | ``` |
| 23 | Vector{ |
| 24 | width: 48 height: 48 |
| 25 | viewbox: vec4(0 0 24 24) |
| 26 | Path{ |
| 27 | d: "M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" |
| 28 | fill: false |
| 29 | stroke: #4488ff |
| 30 | stroke_width: 2.0 |
| 31 | stroke_linecap: "round" |
| 32 | stroke_linejoin: "round" |
| 33 | } |
| 34 | } |
| 35 | ``` |
| 36 | |
| 37 | ### Key Properties |
| 38 | |
| 39 | | Property | Description | Example | |
| 40 | |----------|-------------|---------| |
| 41 | | `width` / `height` | Widget size in pixels | `48` | |
| 42 | | `viewbox` | SVG viewBox as vec4 | `vec4(0 0 24 24)` | |
| 43 | |
| 44 | ### CRITICAL: Shape Properties vs Widget Properties |
| 45 | |
| 46 | **Vector shapes use SVG-style properties, NOT `draw_bg.*` widget properties:** |
| 47 | |
| 48 | ``` |
| 49 | // CORRECT — SVG properties |
| 50 | Path{d:"M 0 0 L 10 10" stroke:#x66aaff stroke_width:2.5} |
| 51 | Circle{cx:10 cy:10 r:5 fill:#x44ddaa} |
| 52 | |
| 53 | // WRONG — these do nothing on Vector shapes! |
| 54 | Path{d:"..." draw_bg.stroke_color:#x66aaff draw_bg.stroke_width:2.} |
| 55 | Circle{cx:10 cy:10 r:5 draw_bg.fill_color:#x44ddaa} |
| 56 | ``` |
| 57 | |
| 58 | --- |
| 59 | |
| 60 | ## Shape Types |
| 61 | |
| 62 | ### Path (SVG path data) |
| 63 | ``` |
| 64 | Path{ |
| 65 | d: "M10 10 L20 20 L10 20 Z" |
| 66 | fill: #f00 |
| 67 | stroke: #000 |
| 68 | stroke_width: 1.5 |
| 69 | } |
| 70 | ``` |
| 71 | |
| 72 | ### Built-in Shapes |
| 73 | ``` |
| 74 | Rect{x: 0 y: 0 width: 100 height: 50 fill: #f00 rx: 5} |
| 75 | Circle{cx: 50 cy: 50 r: 25 fill: #00f} |
| 76 | Ellipse{cx: 50 cy: 30 rx: 40 ry: 20 fill: #0f0} |
| 77 | Line{x1: 0 y1: 0 x2: 100 y2: 100 stroke: #fff stroke_width: 2} |
| 78 | Polyline{points: "0,0 50,25 100,0" fill: false stroke: #fff} |
| 79 | Polygon{points: "50,0 100,100 0,100" fill: #f0f} |
| 80 | ``` |
| 81 | |
| 82 | --- |
| 83 | |
| 84 | ## Gradients |
| 85 | |
| 86 | ### Linear Gradient |
| 87 | ``` |
| 88 | Gradient{ |
| 89 | id: "myGrad" |
| 90 | x1: 0 y1: 0 x2: 1 y2: 1 |
| 91 | Stop{offset: 0 color: #ff0000} |
| 92 | Stop{offset: 1 color: #0000ff} |
| 93 | } |
| 94 | Path{d: "..." fill: "url(#myGrad)"} |
| 95 | ``` |
| 96 | |
| 97 | ### Radial Gradient |
| 98 | ``` |
| 99 | RadGradient{ |
| 100 | id: "radGrad" |
| 101 | cx: 0.5 cy: 0.5 r: 0.5 |
| 102 | Stop{offset: 0 color: #ffffff} |
| 103 | Stop{offset: 1 color: #000000} |
| 104 | } |
| 105 | ``` |
| 106 | |
| 107 | --- |
| 108 | |
| 109 | ## Groups & Transforms |
| 110 | |
| 111 | ``` |
| 112 | Group{ |
| 113 | transform: "translate(10 20) rotate(45 50 50)" |
| 114 | opacity: 0.8 |
| 115 | |
| 116 | Circle{cx: 0 cy: 0 r: 10 fill: #f00} |
| 117 | Rect{x: 20 y: 0 width: 20 height: 20 fill: #0f0} |
| 118 | } |
| 119 | ``` |
| 120 | |
| 121 | --- |
| 122 | |
| 123 | ## Filters |
| 124 | |
| 125 | ``` |
| 126 | Filter{ |
| 127 | id: "shadow" |
| 128 | DropShadow{dx: 2 dy: 2 blur: 4 color: #0008} |
| 129 | } |
| 130 | Path{d: "..." fill: #fff filter: "url(#shadow)"} |
| 131 | ``` |
| 132 | |
| 133 | --- |
| 134 | |
| 135 | ## Tween Animation (SVG Property Animation) |
| 136 | |
| 137 | **CRITICAL:** Tween is a **property value**, NOT a container. It replaces a shape property (fill, stroke, opacity, cx, cy, r, etc.) with an animated value. |
| 138 | |
| 139 | ### Basic Syntax |
| 140 | ``` |
| 141 | // Animate opacity (pulse effect) |
| 142 | Circle{cx:8 cy:8 r:6 fill:#x44ddaa opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:true}} |
| 143 | |
| 144 | // Animate position (moving dot) |
| 145 | Circle{cx:Tween{from:20 to:380 dur:3.0 loop_:true} cy:25 r:5 fill:#x66aaff} |
| 146 | |
| 147 | // Animate color |
| 148 | Circle{fill:Tween{from:#x44ddaa to:#x6688dd dur:3.0 loop_:true} cx:10 cy:10 r:8} |
| 149 | |
| 150 | // Animate stroke |
| 151 | Path{d:"M 0 0 L 100 0" stroke:Tween{from:#x333333 to:#x66aaff dur:2.0 loop_:true} stroke_width:2.} |
| 152 | ``` |
| 153 | |
| 154 | ### CRITICAL: `loop_` Must Be Boolean |
| 155 | ``` |
| 156 | // CORRECT — indefinite loop |
| 157 | opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:true} |
| 158 | |
| 159 | // CORRECT — play 3 times |
| 160 | opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:3.0} |
| 161 | |
| 162 | // WRONG — string doesn't trigger Indefinite, plays only once! |
| 163 | opacity:Tween{from:0.3 to:1.0 dur:1.5 loop_:"indefinite"} |
| 164 | ``` |
| 165 | |
| 166 | ### Tween Properties |
| 167 | |
| 168 | | Property | Type | Description | Default | |
| 169 | |----------|------|-------------|---------| |
| 170 | | `from` | value | Start value (color, float, string) | - | |
| 171 | | `to` | value | End value | - | |
| 172 | | `values` | Vec | Keyframe values (alternative to from/to) | - | |
| 173 | | `dur` | f32 | Duration in seconds | 1.0 | |
| 174 | | `begin` | f32 | Delay offset in seconds | 0.0 | |
| 175 | | `loop_` | bool/f32 | `true` = indefinite, float = repeat count | 1.0 | |
| 176 | | `calc` | string | "discrete", "paced", "spline" | "linear" | |
| 177 | | `fill_mode` | string | "freeze" or "remove" | "remove" | |
| 178 | |
| 179 | ### Animatable Properties |
| 180 | Any shape property can be animated with Tween: |
| 181 | - `fill`, `stroke` — color animation |
| 182 | - `stroke_width`, `opacity`, `stroke_opacity` — flo |