Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion heatmap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ crate-type = ["cdylib"]
opt-level = "z"

[dependencies]
serde-wasm-bindgen = "0.4"
serde-wasm-bindgen = "0.6.5"
serde = { version = "1.0.213", features = ["derive"] }
serde_derive = "1.0"
wasm-bindgen = "0.2.91"
Expand Down
132 changes: 132 additions & 0 deletions heatmap/src/canvas/drawing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
use web_sys::{CanvasRenderingContext2d, console};
use wasm_bindgen::JsValue;

pub fn draw_responsive_heatmap(
context: &CanvasRenderingContext2d,
values: Vec<Vec<i32>>,
x_labels: Vec<String>,
y_labels: Vec<String>,
canvas_width: f64,
canvas_height: f64,
device_pixel_ratio: f64,
) -> Result<(), JsValue>
{
let rows = values.len();
let cols = values[0].len();
console::log_1(&JsValue::from_str(&format!("up in the draw function")));
// Get canvas dimensions
// Calculate dynamic padding and box size
let adj_canvas_width = canvas_width * device_pixel_ratio;
let adj_canvas_height = canvas_height * device_pixel_ratio;
let padding_left = adj_canvas_width * 0.05;
let padding_top = adj_canvas_height * 0.05;
let padding_bottom = adj_canvas_height * 0.05;
let padding_right = adj_canvas_width * 0.05;

// let box_width = (adj_canvas_width - padding_left - padding_right) / (cols as f64 * 1.1);
// let box_height = (adj_canvas_height - padding_top - padding_bottom) / (rows as f64 * 1.1);

let box_width = 30.0;
let box_height = 30.0;
// Clear the canvas
console::log_1(&JsValue::from_str(&format!("pad left {} pad bottom {}",&padding_left, &padding_bottom)));
context.clear_rect(0.0, 0.0, adj_canvas_width, adj_canvas_height);
println!("cleared rec");
// Draw the heatmap
for row in 0..rows {
for col in 0..cols {
let value = values[row][col];

// Set color based on value
let color = match value {
0 => "#fee0d2",
1 => "#fc9272",
2 => "#de2d26",
_ => "#FFFFFF",
};
context.set_fill_style(&JsValue::from_str(color));

let x = padding_left + (col as f64 * box_width);
let y = padding_top + (row as f64 * box_height);
context.fill_rect(x, y, box_width, box_height);

// Draw box borders
context.set_stroke_style(&JsValue::from_str("#FFFFFF"));
context.set_line_width(2.0 / device_pixel_ratio);

if row < rows - 1 {
context.begin_path();
context.move_to(x, y + box_height);
context.line_to(x + box_width, y + box_height);
context.stroke();
}

if col < cols - 1 {
context.begin_path();
context.move_to(x + box_width, y);
context.line_to(x + box_width, y + box_height);
context.stroke();
}
}
}
console::log_1(&JsValue::from_str(&format!(
"after the rows and cols padding bottom: {}, height: {}",
&padding_bottom,
&(box_height * rows as f64),
)));

// Draw X-axis
context.begin_path();
context.set_stroke_style(&JsValue::from_str("#000000"));
context.move_to(padding_left, (box_height * rows as f64) + padding_bottom);
context.line_to((box_height * rows as f64) + padding_bottom, (box_height * rows as f64) + padding_left);
context.stroke();

// Draw Y-axis
context.begin_path();
context.move_to(padding_left, padding_top);
context.line_to(padding_left, (box_height * rows as f64) + padding_bottom);
context.stroke();

// Draw X-axis ticks and labels
let label_font_size = (box_height * 0.3).min(box_width * 0.3).max(12.0);
context.set_font(&format!("{}px Arial", label_font_size));
context.set_text_align("center");
context.set_text_baseline("top");

for col in 0..cols {
let x = padding_left + col as f64 * box_width + box_width / 2.0;
let y = (box_height * rows as f64) + padding_bottom + 5.0; // Position below the heatmap
context.fill_text(&x_labels[col], x, y)
.map_err(|_| JsValue::from_str(&format!("Failed to draw text at column {}", col)))?;

// Draw ticks
context.begin_path();
context.move_to(x, (box_height * rows as f64) + padding_bottom);
context.line_to(x, (box_height * rows as f64) + padding_bottom + 5.0);
context.stroke();
}

// Draw Y-axis ticks and labels
context.set_text_align("right");
context.set_text_baseline("middle");

for row in 0..rows {
let x = padding_left - 10.0; // Position to the left of the heatmap
let y = padding_top + row as f64 * box_height + box_height / 2.0;
context.fill_text(&y_labels[row], x, y)
.map_err(|_| JsValue::from_str(&format!("Failed to draw text at row {}", row)))?;

// Draw ticks
context.begin_path();
context.move_to(padding_left, y);
context.line_to(padding_left - 5.0, y);
context.stroke();
}
console::log_1(&JsValue::from_str(&format!(
"at the end of draw funct Canvas width: {}, height: {}",
&adj_canvas_width,
&adj_canvas_height
)));
Ok(())
}
1 change: 1 addition & 0 deletions heatmap/src/canvas/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod drawing;
34 changes: 34 additions & 0 deletions heatmap/src/heatmap_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//! This module contains the data structure for the heatmap

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct HeatmapData {
pub values: Vec<Vec<i32>>,
pub x_labels: Vec<String>,
pub y_labels: Vec<String>,
}

impl HeatmapData {
// Constructor method
pub fn new() -> Self {
HeatmapData {
values: vec![vec![0]],
x_labels: Vec::new(),
y_labels: Vec::new(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_new() {
let heatmap_data = HeatmapData::new();
assert_eq!(heatmap_data.values, vec![vec![0]]);
assert_eq!(heatmap_data.x_labels, Vec::<String>::new());
assert_eq!(heatmap_data.y_labels, Vec::<String>::new());
}
}
Loading