Add the right-click ability on avatars
This commit is contained in:
parent
d1cbb3ba34
commit
0492043625
7 changed files with 438 additions and 2 deletions
|
|
@ -528,6 +528,69 @@ fn wrap_text(ctx: &web_sys::CanvasRenderingContext2d, text: &str, max_width: f64
|
|||
lines
|
||||
}
|
||||
|
||||
/// Test if a click at the given client coordinates hits a non-transparent pixel.
|
||||
///
|
||||
/// Returns true if the alpha channel at the clicked pixel is > 0.
|
||||
/// This enables pixel-perfect hit detection on avatar canvases.
|
||||
#[cfg(feature = "hydrate")]
|
||||
pub fn hit_test_canvas(
|
||||
canvas: &web_sys::HtmlCanvasElement,
|
||||
client_x: f64,
|
||||
client_y: f64,
|
||||
) -> bool {
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
// Get the canvas bounding rect to transform client coords to canvas coords
|
||||
let rect = canvas.get_bounding_client_rect();
|
||||
|
||||
// Calculate click position relative to the canvas element
|
||||
let relative_x = client_x - rect.left();
|
||||
let relative_y = client_y - rect.top();
|
||||
|
||||
// Check if click is within canvas bounds
|
||||
if relative_x < 0.0 || relative_y < 0.0 || relative_x >= rect.width() || relative_y >= rect.height() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Transform to canvas pixel coordinates (accounting for CSS scaling)
|
||||
let canvas_width = canvas.width() as f64;
|
||||
let canvas_height = canvas.height() as f64;
|
||||
|
||||
// Avoid division by zero
|
||||
if rect.width() == 0.0 || rect.height() == 0.0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
let scale_x = canvas_width / rect.width();
|
||||
let scale_y = canvas_height / rect.height();
|
||||
|
||||
let pixel_x = (relative_x * scale_x) as f64;
|
||||
let pixel_y = (relative_y * scale_y) as f64;
|
||||
|
||||
// Get the 2D context and read the pixel data using JavaScript interop
|
||||
if let Ok(Some(ctx)) = canvas.get_context("2d") {
|
||||
let ctx: web_sys::CanvasRenderingContext2d = ctx.dyn_into().unwrap();
|
||||
|
||||
// Use web_sys::CanvasRenderingContext2d::get_image_data with proper error handling
|
||||
match ctx.get_image_data(pixel_x, pixel_y, 1.0, 1.0) {
|
||||
Ok(image_data) => {
|
||||
// Get the pixel data as Clamped<Vec<u8>>
|
||||
let data = image_data.data();
|
||||
// Alpha channel is the 4th value (index 3)
|
||||
if data.len() >= 4 {
|
||||
return data[3] > 0;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Security error or other issue with getImageData - assume no hit
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Draw a rounded rectangle path.
|
||||
#[cfg(feature = "hydrate")]
|
||||
fn draw_rounded_rect(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue