diff --git a/dist/index.html b/dist/index.html
index 2efed2a..3573f06 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -2,6 +2,15 @@
Queer Mandelbrot
+
diff --git a/src/canvas.mjs b/src/canvas.mjs
index 9d7af0c..3659b7b 100644
--- a/src/canvas.mjs
+++ b/src/canvas.mjs
@@ -2,7 +2,36 @@
export const getContext = (id) =>
document.getElementById(id).getContext("2d");
+export const getInnerWidth = () =>
+ window.innerWidth;
+
+export const getInnerHeight = () =>
+ window.innerHeight;
+
+export const onResize = (callback) =>
+ window.addEventListener("resize", callback);
+
export const setPixel = (ctx, x, y, color) => {
ctx.fillStyle = color;
ctx.fillRect(x, y, 1, 1);
};
+
+export const clear = (ctx) => {
+ ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
+};
+
+export const setSize = (ctx, width, height) => {
+ ctx.canvas.width = width;
+ ctx.canvas.height = height;
+};
+
+export const requestAnimationFrame = (callback) => {
+ let eventListener = () => {
+ callback();
+ window.removeEventListener("message", eventListener);
+ }
+
+ window.addEventListener("message", eventListener)
+ window.postMessage(null);
+};
+//window.requestAnimationFrame;
diff --git a/src/queermandelbrot.gleam b/src/queermandelbrot.gleam
index 650a646..58a4362 100644
--- a/src/queermandelbrot.gleam
+++ b/src/queermandelbrot.gleam
@@ -70,41 +70,81 @@ fn value_to_color(colorscheme: ColorScheme, value: Int) -> String {
}
}
-pub fn main() {
+fn animate_for_each(
+ list: List(a),
+ still_valid: fn() -> Bool,
+ callback: fn(a) -> Nil,
+) -> Nil {
+ case list, still_valid() {
+ _, False -> Nil
+ [], True -> Nil
+ [head, ..rest], True -> {
+ callback(head)
+ request_animation_frame(fn() {
+ animate_for_each(rest, still_valid, callback)
+ })
+ }
+ }
+}
+
+fn redraw(ctx: Context2D, canvas_width: Int, canvas_height: Int) {
let colorscheme = Lesbian
- let ctx = get_context("mandelbrot")
+ set_size(ctx, canvas_width, canvas_height)
+ clear(ctx)
- let canvas_width = 600
- let canvas_height = 400
let min_x = -2.0
let max_x = 1.0
let min_y = -1.0
let max_y = 1.0
list.range(0, canvas_width - 1)
- |> list.each(fn(x) {
- list.range(0, canvas_height - 1)
- |> list.each(fn(y) {
- let location =
- Complex(
- real: int.to_float(x)
- /. int.to_float(canvas_width)
- *. { max_x -. min_x }
- +. min_x,
- imaginary: int.to_float(y)
- /. int.to_float(canvas_height)
- *. { max_y -. min_y }
- +. min_y,
- )
- let value = get_mandelbrot_value(location, 1000.0, Complex(0.0, 0.0), 0)
- case value {
- Converges -> set_pixel(ctx, x, y, "#000")
- Diverges(value) ->
- set_pixel(ctx, x, y, value_to_color(colorscheme, value))
- }
- })
- })
+ |> list.sized_chunk(1)
+ |> animate_for_each(
+ fn() {
+ get_inner_width() == canvas_width && get_inner_height() == canvas_height
+ },
+ list.each(_, fn(x) {
+ io.debug(x)
+ list.range(0, canvas_height - 1)
+ |> list.each(fn(y) {
+ let pad_horizontal =
+ { max_x -. min_x } /. { max_y -. min_y }
+ <. int.to_float(canvas_width) /. int.to_float(canvas_height)
+
+ let #(sizing_factor, x_offset, y_offset) = case pad_horizontal {
+ True -> #(canvas_height, min_x, min_y)
+ False -> #(canvas_width, min_x, min_y)
+ }
+
+ let location =
+ Complex(
+ real: int.to_float(x)
+ /. int.to_float(sizing_factor)
+ *. { max_x -. min_x }
+ +. x_offset,
+ imaginary: int.to_float(y)
+ /. int.to_float(sizing_factor)
+ *. { max_y -. min_y }
+ +. y_offset,
+ )
+ let value = get_mandelbrot_value(location, 1000.0, Complex(0.0, 0.0), 0)
+ case value {
+ Converges -> set_pixel(ctx, x, y, "#000")
+ Diverges(value) ->
+ set_pixel(ctx, x, y, value_to_color(colorscheme, value))
+ }
+ })
+ }),
+ )
+}
+
+pub fn main() {
+ let ctx = get_context("mandelbrot")
+
+ redraw(ctx, get_inner_width(), get_inner_height())
+
+ on_resize(fn() { redraw(ctx, get_inner_width(), get_inner_height()) })
}
type Context2D
@@ -112,5 +152,23 @@ type Context2D
@external(javascript, "./canvas.mjs", "getContext")
fn get_context(id: String) -> Context2D
+@external(javascript, "./canvas.mjs", "getInnerWidth")
+fn get_inner_width() -> Int
+
+@external(javascript, "./canvas.mjs", "getInnerHeight")
+fn get_inner_height() -> Int
+
+@external(javascript, "./canvas.mjs", "onResize")
+fn on_resize(callback: fn() -> Nil) -> Nil
+
@external(javascript, "./canvas.mjs", "setPixel")
fn set_pixel(ctx: Context2D, x: Int, y: Int, color: String) -> Nil
+
+@external(javascript, "./canvas.mjs", "clear")
+fn clear(ctx: Context2D) -> Nil
+
+@external(javascript, "./canvas.mjs", "setSize")
+fn set_size(ctx: Context2D, width: Int, height: Int) -> Nil
+
+@external(javascript, "./canvas.mjs", "requestAnimationFrame")
+fn request_animation_frame(callback: fn() -> Nil) -> Nil