gpui: Add linear gradient support to fill background (#20812)
Release Notes: - gpui: Add linear gradient support to fill background Run example: ``` cargo run -p gpui --example gradient cargo run -p gpui --example gradient --features macos-blade ``` ## Demo In GPUI (sRGB): <img width="761" alt="image" src="https://github.com/user-attachments/assets/568c02e8-3065-43c2-b5c2-5618d553dd6e"> In GPUI (Oklab): <img width="761" alt="image" src="https://github.com/user-attachments/assets/b008b0de-2705-4f99-831d-998ce48eed42"> In CSS (sRGB): https://codepen.io/huacnlee/pen/rNXgxBY <img width="505" alt="image" src="https://github.com/user-attachments/assets/239f4b65-24b3-4797-9491-a13eea420158"> In CSS (Oklab): https://codepen.io/huacnlee/pen/wBwBKOp <img width="658" alt="image" src="https://github.com/user-attachments/assets/56fdd55f-d219-45de-922f-7227f535b210"> --- Currently only support 2 color stops with linear-gradient. I think this is we first introduce the gradient feature in GPUI, and the linear-gradient is most popular for use. So we can just add this first and then to add more other supports.
This commit is contained in:
parent
c594ccb0af
commit
de89f8cf83
9 changed files with 902 additions and 73 deletions
254
crates/gpui/examples/gradient.rs
Normal file
254
crates/gpui/examples/gradient.rs
Normal file
|
@ -0,0 +1,254 @@
|
|||
use gpui::{
|
||||
canvas, div, linear_color_stop, linear_gradient, point, prelude::*, px, size, App, AppContext,
|
||||
Bounds, ColorSpace, Half, Render, ViewContext, WindowOptions,
|
||||
};
|
||||
|
||||
struct GradientViewer {
|
||||
color_space: ColorSpace,
|
||||
}
|
||||
|
||||
impl GradientViewer {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
color_space: ColorSpace::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for GradientViewer {
|
||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||
let color_space = self.color_space;
|
||||
|
||||
div()
|
||||
.font_family(".SystemUIFont")
|
||||
.bg(gpui::white())
|
||||
.size_full()
|
||||
.p_4()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.gap_2()
|
||||
.justify_between()
|
||||
.items_center()
|
||||
.child("Gradient Examples")
|
||||
.child(
|
||||
div().flex().gap_2().items_center().child(
|
||||
div()
|
||||
.id("method")
|
||||
.flex()
|
||||
.px_3()
|
||||
.py_1()
|
||||
.text_sm()
|
||||
.bg(gpui::black())
|
||||
.text_color(gpui::white())
|
||||
.child(format!("{}", color_space))
|
||||
.active(|this| this.opacity(0.8))
|
||||
.on_click(cx.listener(move |this, _, cx| {
|
||||
this.color_space = match this.color_space {
|
||||
ColorSpace::Oklab => ColorSpace::Srgb,
|
||||
ColorSpace::Srgb => ColorSpace::Oklab,
|
||||
};
|
||||
cx.notify();
|
||||
})),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_1()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.size_full()
|
||||
.rounded_xl()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.bg(gpui::red())
|
||||
.text_color(gpui::white())
|
||||
.child("Solid Color"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.size_full()
|
||||
.rounded_xl()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.bg(gpui::blue())
|
||||
.text_color(gpui::white())
|
||||
.child("Solid Color"),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_1()
|
||||
.gap_3()
|
||||
.h_24()
|
||||
.text_color(gpui::white())
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
45.,
|
||||
linear_color_stop(gpui::red(), 0.),
|
||||
linear_color_stop(gpui::blue(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
135.,
|
||||
linear_color_stop(gpui::red(), 0.),
|
||||
linear_color_stop(gpui::green(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
225.,
|
||||
linear_color_stop(gpui::green(), 0.),
|
||||
linear_color_stop(gpui::blue(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
315.,
|
||||
linear_color_stop(gpui::green(), 0.),
|
||||
linear_color_stop(gpui::yellow(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_1()
|
||||
.gap_3()
|
||||
.h_24()
|
||||
.text_color(gpui::white())
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
0.,
|
||||
linear_color_stop(gpui::red(), 0.),
|
||||
linear_color_stop(gpui::white(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
90.,
|
||||
linear_color_stop(gpui::blue(), 0.),
|
||||
linear_color_stop(gpui::white(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
180.,
|
||||
linear_color_stop(gpui::green(), 0.),
|
||||
linear_color_stop(gpui::white(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
360.,
|
||||
linear_color_stop(gpui::yellow(), 0.),
|
||||
linear_color_stop(gpui::white(), 1.),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
0.,
|
||||
linear_color_stop(gpui::green(), 0.05),
|
||||
linear_color_stop(gpui::yellow(), 0.95),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
90.,
|
||||
linear_color_stop(gpui::blue(), 0.05),
|
||||
linear_color_stop(gpui::red(), 0.95),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_1()
|
||||
.gap_3()
|
||||
.child(
|
||||
div().flex().flex_1().gap_3().child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
90.,
|
||||
linear_color_stop(gpui::blue(), 0.5),
|
||||
linear_color_stop(gpui::red(), 0.5),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div().flex_1().rounded_xl().bg(linear_gradient(
|
||||
180.,
|
||||
linear_color_stop(gpui::green(), 0.),
|
||||
linear_color_stop(gpui::blue(), 0.5),
|
||||
)
|
||||
.color_space(color_space)),
|
||||
),
|
||||
)
|
||||
.child(div().h_24().child(canvas(
|
||||
move |_, _| {},
|
||||
move |bounds, _, cx| {
|
||||
let size = size(bounds.size.width * 0.8, px(80.));
|
||||
let square_bounds = Bounds {
|
||||
origin: point(
|
||||
bounds.size.width.half() - size.width.half(),
|
||||
bounds.origin.y,
|
||||
),
|
||||
size,
|
||||
};
|
||||
let height = square_bounds.size.height;
|
||||
let horizontal_offset = height;
|
||||
let vertical_offset = px(30.);
|
||||
let mut path = gpui::Path::new(square_bounds.lower_left());
|
||||
path.line_to(square_bounds.origin + point(horizontal_offset, vertical_offset));
|
||||
path.line_to(
|
||||
square_bounds.upper_right() + point(-horizontal_offset, vertical_offset),
|
||||
);
|
||||
path.line_to(square_bounds.lower_right());
|
||||
path.line_to(square_bounds.lower_left());
|
||||
cx.paint_path(
|
||||
path,
|
||||
linear_gradient(
|
||||
180.,
|
||||
linear_color_stop(gpui::red(), 0.),
|
||||
linear_color_stop(gpui::blue(), 1.),
|
||||
)
|
||||
.color_space(color_space),
|
||||
);
|
||||
},
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
App::new().run(|cx: &mut AppContext| {
|
||||
cx.open_window(
|
||||
WindowOptions {
|
||||
focus: true,
|
||||
..Default::default()
|
||||
},
|
||||
|cx| cx.new_view(|_| GradientViewer::new()),
|
||||
)
|
||||
.unwrap();
|
||||
cx.activate(true);
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue