---
title: "Componente BlendModes — zenit Zig UI"
description: "Modos de fusión y composición con opacidad. Cada modo de fusión tiene aserciones por píxel para que la GPU nunca degrade a alpha simple."
url: https://zenit.z.express/es/components/blend
language: es
alternate_en: https://zenit.z.express/components/blend.md
alternate_zh: https://zenit.z.express/zh/components/blend.md
alternate_ja: https://zenit.z.express/ja/components/blend.md
alternate_ko: https://zenit.z.express/ko/components/blend.md
alternate_fr: https://zenit.z.express/fr/components/blend.md
alternate_de: https://zenit.z.express/de/components/blend.md
project: zenit v0.1.0-alpha (Zig 0.15.2, macOS)
source: https://github.com/version-next/zenit
---

# BlendModes

`ui.box`

Modos de fusión y composición con opacidad.

[Video](https://zenit.z.express/media/stories/blend.mp4?v=6046256a2f)

**BEHAVIOR CONTRACT**

Cada modo de fusión tiene aserciones por píxel para que la GPU nunca degrade a alpha simple.

**RECORDED INTERACTION**

Recorre la matriz de modos de fusión.

`examples/storybook/stories.zig:3326`

```zig
// 颜色特意全用 0/255 分量：sRGB 传递函数在 0.0/1.0 处不变，线性空间与
// sRGB 空间的混合结果一致 —— e2e 能按精确 RGB 值断言，不受"shader 在
// 线性空间混合"这一实现细节影响。
//   multiply:   yellow(255,255,0) × cyan(0,255,255)  = green(0,255,0)
//   screen:     red(255,0,0)    ∪ blue(0,0,255)      = magenta(255,0,255)
//   difference: |white(255,255,255) − red(255,0,0)|  = cyan(0,255,255)
pub fn buildBlend(scope: *ui.Scope, cx: *ui.Cx) anyerror!*ui.Node {
    _ = scope;
    const a = cx.allocator;
    const c = try col(cx, 16);

    const Case = struct {
        name: []const u8,
        test_id: []const u8,
        bg: ui.Color,
        src: ui.Color,
        mode: ui.BlendMode,
    };
    const cases = [_]Case{
        .{ .name = "multiply: yellow x cyan = green", .test_id = "story.blend.multiply", .bg = ui.Color.rgb(255, 255, 0), .src = ui.Color.rgb(0, 255, 255), .mode = .multiply },
        .{ .name = "screen: red + blue = magenta", .test_id = "story.blend.screen", .bg = ui.Color.rgb(255, 0, 0), .src = ui.Color.rgb(0, 0, 255), .mode = .screen },
        .{ .name = "difference: white - red = cyan", .test_id = "story.blend.difference", .bg = ui.Color.rgb(255, 255, 255), .src = ui.Color.rgb(255, 0, 0), .mode = .difference },
    };

    try c.appendChild(a, try label(cx, "Blend modes (exact-color e2e targets)"));
    const tiles = try row(cx, 16);
    for (cases) |case| {
        const cell = try col(cx, 6);
        try cell.appendChild(a, try label(cx, case.name));
        const outer = try ui.box(cx, .{
            .width = .{ .px = 120 },
            .height = .{ .px = 120 },
            .background = case.bg,
            .padding = ui.Padding.all(20),
        }, .{});
        const inner = try ui.box(cx, .{
            .width = .{ .px = 80 },
            .height = .{ .px = 80 },
            .background = case.src,
        }, .{});
        (try inner.style.ensureExtFallible(a)).blend_mode = case.mode;
        inner.meta.ownership.meta.test_id = case.test_id;
        try outer.appendChild(a, inner);
        try cell.appendChild(a, outer);
        try tiles.appendChild(a, cell);
    }
    try c.appendChild(a, tiles);

    // normal 对照组：同 cyan-on-yellow 但不混合 —— e2e 断言它仍是 cyan，
    // 证明 blend 路径没把普通合成一起改了。
    try c.appendChild(a, try label(cx, "normal control (should stay cyan)"));
    const control_outer = try ui.box(cx, .{
        .width = .{ .px = 120 },
        .height = .{ .px = 120 },
        .background = ui.Color.rgb(255, 255, 0),
        .padding = ui.Padding.all(20),
    }, .{});
    const control_inner = try ui.box(cx, .{
        .width = .{ .px = 80 },
        .height = .{ .px = 80 },
        .background = ui.Color.rgb(0, 255, 255),
    }, .{});
    control_inner.meta.ownership.meta.test_id = "story.blend.control";
    try control_outer.appendChild(a, control_inner);
    try c.appendChild(a, control_outer);

    return c;
}
```

[Ver el código en GitHubexamples/storybook/stories.zig:3326](https://github.com/version-next/zenit/blob/HEAD/examples/storybook/stories.zig#L3326)

El código literal de la story en el Storybook (zenit 5f9add5+wip 2026-09-30). `W` es `ui.widgets`; `col` / `row` / `label` son pequeños helpers de layout del Storybook.
