feat(animation): ColorTransition para transiciones suaves de color
Transiciones Suaves (Acabado Espectacular mejora #4): - Nuevo struct ColorTransition en animation.zig - Interpola colores en ~200ms usando lerp - Se inicializa automáticamente en primer uso - Exportado en zcatgui.zig junto con HoverTransition Uso: state.bg_transition.update(target_color, delta_ms) ctx.drawRect(..., state.bg_transition.current) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
c657583e06
commit
f0f9120da0
2 changed files with 99 additions and 0 deletions
|
|
@ -678,6 +678,103 @@ pub const HoverTransition = struct {
|
|||
}
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// Color Transition (for panel backgrounds)
|
||||
// =============================================================================
|
||||
|
||||
const Style = @import("../core/style.zig");
|
||||
|
||||
/// Smooth color transition for panel backgrounds.
|
||||
/// Interpolates from current to target color over ~200ms.
|
||||
///
|
||||
/// Usage:
|
||||
/// ```zig
|
||||
/// pub const PanelState = struct {
|
||||
/// bg_transition: ColorTransition = .{},
|
||||
/// };
|
||||
///
|
||||
/// // In panel draw:
|
||||
/// const target_color = if (has_focus) focus_color else normal_color;
|
||||
/// state.bg_transition.update(target_color, ctx.delta_ms);
|
||||
/// const display_color = state.bg_transition.current;
|
||||
/// ctx.drawRect(..., display_color);
|
||||
/// ```
|
||||
pub const ColorTransition = struct {
|
||||
/// Current displayed color
|
||||
current: Style.Color = Style.Color.rgb(0, 0, 0),
|
||||
/// Is initialized with a color?
|
||||
initialized: bool = false,
|
||||
/// Transition duration in milliseconds
|
||||
duration_ms: f32 = 200.0,
|
||||
|
||||
const Self = @This();
|
||||
|
||||
/// Update transition towards target color
|
||||
/// Returns true if color changed (for requesting redraw)
|
||||
pub fn update(self: *Self, target: Style.Color, delta_ms: u64) bool {
|
||||
// First call: snap to target immediately
|
||||
if (!self.initialized) {
|
||||
self.current = target;
|
||||
self.initialized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Already at target?
|
||||
if (self.current.r == target.r and
|
||||
self.current.g == target.g and
|
||||
self.current.b == target.b and
|
||||
self.current.a == target.a)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculate interpolation factor (chase towards target)
|
||||
const t = @min(1.0, @as(f32, @floatFromInt(delta_ms)) / self.duration_ms);
|
||||
|
||||
// Interpolate each channel
|
||||
self.current = Style.Color{
|
||||
.r = lerpU8(self.current.r, target.r, t),
|
||||
.g = lerpU8(self.current.g, target.g, t),
|
||||
.b = lerpU8(self.current.b, target.b, t),
|
||||
.a = lerpU8(self.current.a, target.a, t),
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Reset to uninitialized state
|
||||
pub fn reset(self: *Self) void {
|
||||
self.initialized = false;
|
||||
}
|
||||
};
|
||||
|
||||
/// Interpolate between two u8 values
|
||||
fn lerpU8(a: u8, b: u8, t: f32) u8 {
|
||||
const af: f32 = @floatFromInt(a);
|
||||
const bf: f32 = @floatFromInt(b);
|
||||
return @intFromFloat(af + (bf - af) * t);
|
||||
}
|
||||
|
||||
test "ColorTransition basic" {
|
||||
var trans = ColorTransition{};
|
||||
const black = Style.Color.rgb(0, 0, 0);
|
||||
const white = Style.Color.rgb(255, 255, 255);
|
||||
|
||||
// First update snaps to target
|
||||
_ = trans.update(black, 16);
|
||||
try std.testing.expect(trans.initialized);
|
||||
try std.testing.expectEqual(@as(u8, 0), trans.current.r);
|
||||
|
||||
// Transition towards white over time
|
||||
_ = trans.update(white, 100); // ~50% transition
|
||||
try std.testing.expect(trans.current.r > 0);
|
||||
try std.testing.expect(trans.current.r < 255);
|
||||
|
||||
// Full duration reaches target
|
||||
_ = trans.update(white, 200);
|
||||
try std.testing.expectEqual(@as(u8, 255), trans.current.r);
|
||||
}
|
||||
|
||||
test "HoverTransition basic" {
|
||||
var hover = HoverTransition{};
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ pub const lerp = render.animation.lerp;
|
|||
pub const lerpInt = render.animation.lerpInt;
|
||||
pub const Spring = render.animation.Spring;
|
||||
pub const SpringConfig = render.animation.SpringConfig;
|
||||
pub const HoverTransition = render.animation.HoverTransition;
|
||||
pub const ColorTransition = render.animation.ColorTransition;
|
||||
|
||||
// Effects re-exports
|
||||
pub const Shadow = render.effects.Shadow;
|
||||
|
|
|
|||
Loading…
Reference in a new issue