mirror of
https://github.com/sigmasternchen/queermandelbrot
synced 2025-03-16 00:08:59 +00:00
feat: change to fullscreen and progressive rendering
This commit is contained in:
parent
4211fc3074
commit
68f7c53c64
3 changed files with 122 additions and 26 deletions
9
dist/index.html
vendored
9
dist/index.html
vendored
|
@ -2,6 +2,15 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Queer Mandelbrot</title>
|
||||
<style>
|
||||
#mandelbrot {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="mandelbrot" width="600" height="400"></canvas>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue