Рабочий зум

This commit is contained in:
2025-12-19 21:57:51 +03:00
parent 183726aed4
commit e22051c1c1
4 changed files with 73 additions and 48 deletions

View File

@@ -1,19 +1,22 @@
const std = @import("std");
const dvui = @import("dvui");
const Size = dvui.Size;
const Color = dvui.Color;
const Canvas = @This();
allocator: std.mem.Allocator,
texture: ?dvui.Texture = null,
width: u32 = 400,
height: u32 = 300,
size: Size = .{ .w = 800, .h = 600 },
pos: dvui.Point = dvui.Point{ .x = 0, .y = 0 },
scroll: dvui.ScrollInfo = .{
.vertical = .given,
.horizontal = .given,
.virtual_size = .{ .w = 2000, .h = 2000 },
.vertical = .auto,
.horizontal = .auto,
// .virtual_size = .{ .w = 2000, .h = 2000 },
},
zoom: f32 = 1,
gradient_start: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 },
gradient_end: Color.PMA = .{ .r = 255, .g = 255, .b = 255, .a = 255 },
pub fn init(allocator: std.mem.Allocator) Canvas {
return .{ .allocator = allocator };
@@ -27,26 +30,24 @@ pub fn deinit(self: *Canvas) void {
}
/// Заполнить canvas градиентом
pub fn fillRandomColor(self: *Canvas) !void {
pub fn redrawGradient(self: *Canvas) !void {
std.debug.print("Zoom: {any}\n", .{self.zoom});
const width: u32 = @intFromFloat(self.size.w * self.zoom);
const height: u32 = @intFromFloat(self.size.h * self.zoom);
// Выделить буфер пиксельных данных
const pixels = try self.allocator.alloc(Color.PMA, @as(usize, self.width) * self.height);
const pixels = try self.allocator.alloc(Color.PMA, @as(usize, width) * height);
defer self.allocator.free(pixels);
// Сгенерировать случайные цвета градиента
var prng = std.Random.DefaultPrng.init(@intCast(std.time.microTimestamp()));
const random = prng.random();
const start_color = Color.PMA{ .r = random.int(u8), .g = random.int(u8), .b = random.int(u8), .a = 255 };
const end_color = Color.PMA{ .r = random.int(u8), .g = random.int(u8), .b = random.int(u8), .a = 255 };
var y: u32 = 0;
while (y < self.height) : (y += 1) {
while (y < height) : (y += 1) {
var x: u32 = 0;
while (x < self.width) : (x += 1) {
const factor = @as(f32, @floatFromInt(x)) / @as(f32, @floatFromInt(self.width - 1));
const r = @as(u8, @intFromFloat(@as(f32, @floatFromInt(start_color.r)) + factor * (@as(f32, @floatFromInt(end_color.r)) - @as(f32, @floatFromInt(start_color.r)))));
const g = @as(u8, @intFromFloat(@as(f32, @floatFromInt(start_color.g)) + factor * (@as(f32, @floatFromInt(end_color.g)) - @as(f32, @floatFromInt(start_color.g)))));
const b = @as(u8, @intFromFloat(@as(f32, @floatFromInt(start_color.b)) + factor * (@as(f32, @floatFromInt(end_color.b)) - @as(f32, @floatFromInt(start_color.b)))));
pixels[y * self.width + x] = .{ .r = r, .g = g, .b = b, .a = 255 };
while (x < width) : (x += 1) {
const factor = (@as(f32, @floatFromInt(x)) / @as(f32, @floatFromInt(width - 1)) + @as(f32, @floatFromInt(y)) / @as(f32, @floatFromInt(height - 1))) / 2;
const r = @as(u8, @intFromFloat(@as(f32, @floatFromInt(self.gradient_start.r)) + factor * (@as(f32, @floatFromInt(self.gradient_end.r)) - @as(f32, @floatFromInt(self.gradient_start.r)))));
const g = @as(u8, @intFromFloat(@as(f32, @floatFromInt(self.gradient_start.g)) + factor * (@as(f32, @floatFromInt(self.gradient_end.g)) - @as(f32, @floatFromInt(self.gradient_start.g)))));
const b = @as(u8, @intFromFloat(@as(f32, @floatFromInt(self.gradient_start.b)) + factor * (@as(f32, @floatFromInt(self.gradient_end.b)) - @as(f32, @floatFromInt(self.gradient_start.b)))));
pixels[y * width + x] = .{ .r = r, .g = g, .b = b, .a = 255 };
}
}
@@ -56,13 +57,23 @@ pub fn fillRandomColor(self: *Canvas) !void {
}
// Создать новую текстуру из пиксельных данных
self.texture = try dvui.textureCreate(pixels, self.width, self.height, .linear);
self.texture = try dvui.textureCreate(pixels, width, height, .nearest);
}
// Дать скроллам ощутимый диапазон сразу (минимум 2000x2000)
self.scroll.virtual_size = .{
.w = @max(2000, @as(f32, @floatFromInt(self.width))),
.h = @max(2000, @as(f32, @floatFromInt(self.height))),
};
/// Заполнить canvas случайным градиентом
pub fn fillRandomGradient(self: *Canvas) !void {
// Сгенерировать случайные цвета градиента
var prng = std.Random.DefaultPrng.init(@intCast(std.time.microTimestamp()));
const random = prng.random();
self.gradient_start = Color.PMA{ .r = random.int(u8), .g = random.int(u8), .b = random.int(u8), .a = 255 };
self.gradient_end = Color.PMA{ .r = random.int(u8), .g = random.int(u8), .b = random.int(u8), .a = 255 };
try self.redrawGradient();
}
pub fn addZoom(self: *Canvas, value: f32) void {
self.zoom += value;
self.zoom = @max(self.zoom, 0.01);
}
/// Отобразить canvas в UI