*)
open Js_of_ocaml
+open Js_of_ocaml_lwt
-let canvas =
- match Dom_html.getElementById_coerce "canvas" Dom_html.CoerceTo.canvas with
+let get_elem_id id coercion =
+ match Dom_html.getElementById_coerce id coercion with
| Some canvas -> canvas
- | None -> failwith "No canvas."
+ | None -> failwith ("No " ^ id ^ ".")
+
+let canvas = get_elem_id "canvas" Dom_html.CoerceTo.canvas
let ctx = canvas##getContext Dom_html._2d_
let t = Float.pi *. 2. *. t in
Shape.Vector.(Notation.(c + (r * fromAngle t))))
-let marbling : (Shape.t * Js.js_string Js.t) list ref = ref []
-
-let marbling_view : (Shape.t * Js.js_string Js.t) list ref = ref []
-
let add_drop c r color marbling =
List.fold_right (fun (sh, color) rest -> (apply_drop c r sh, color) :: rest) marbling [(drop c r, color)]
-let main () =
- ctx##.fillStyle := Js.string "#00001f";
- ctx##fillRect 0.0 0.0 (float_of_int canvas##.width) (float_of_int canvas##.height);
- List.iter
- (fun (shape, color) ->
- ctx##.fillStyle := color;
- Shape.path ctx shape;
- ctx##fill)
- !marbling_view
+open Lwt.Syntax
-let _interval_id = Dom_html.window##setInterval (Js.wrap_callback main) (1000.0 /. 60.0)
+type event = Click of (float * float) | Unclick of (float * float) | Move of (float * float) | Out
-let _mousemove_listener, _mousedown_listener, _mouseout_listener =
- let r = ref 0.
- and color = ref (Js.string "") in
- let reset () =
- r := Random.float 50. +. 25.;
- color :=
- Js.string
- ("rgb("
- ^ string_of_int (Random.int 128 + 127)
- ^ " "
- ^ string_of_int (Random.int 128 + 127)
- ^ " "
- ^ string_of_int (Random.int 128 + 127)
- ^ ")")
+let rec main marbling p () =
+ let r = Random.float 50. +. 25.
+ and color =
+ Js.string
+ ("rgb("
+ ^ string_of_int (Random.int 128 + 127)
+ ^ " "
+ ^ string_of_int (Random.int 128 + 127)
+ ^ " "
+ ^ string_of_int (Random.int 128 + 127)
+ ^ ")")
in
- reset ();
- ( Dom_html.addEventListener canvas Dom_html.Event.mousemove
- (Dom.handler (fun ev ->
- marbling_view := add_drop (float_of_int ev##.offsetX, float_of_int ev##.offsetY) !r !color !marbling;
- Js.bool true))
- (Js.bool false),
- Dom_html.addEventListener canvas Dom_html.Event.mousedown
- (Dom.handler (fun ev ->
- marbling := add_drop (float_of_int ev##.offsetX, float_of_int ev##.offsetY) !r !color !marbling;
- reset ();
- marbling_view := add_drop (float_of_int ev##.offsetX, float_of_int ev##.offsetY) !r !color !marbling;
- Js.bool true))
- (Js.bool false),
- Dom_html.addEventListener canvas Dom_html.Event.mouseout
- (Dom.handler (fun _ev ->
- marbling_view := !marbling;
- Js.bool true))
- (Js.bool false) )
+ let rec with_drop_info marbling_view =
+ ctx##.fillStyle := Js.string "#00001f";
+ ctx##fillRect 0.0 0.0 (float_of_int canvas##.width) (float_of_int canvas##.height);
+ List.iter
+ (fun (shape, color) ->
+ ctx##.fillStyle := color;
+ Shape.path ctx shape;
+ ctx##fill)
+ marbling_view;
+ let* ev =
+ Lwt.pick
+ Lwt_js_events.
+ [
+ (let+ ev = mousedown canvas in
+ Click (float_of_int ev##.offsetX, float_of_int ev##.offsetY));
+ (let+ ev = mouseup canvas in
+ Unclick (float_of_int ev##.offsetX, float_of_int ev##.offsetY));
+ (let+ ev = mousemove canvas in
+ Move (float_of_int ev##.offsetX, float_of_int ev##.offsetY));
+ (let+ _ = mouseout canvas in
+ Out);
+ ]
+ in
+ match ev with
+ | Click p -> with_drop_info (add_drop p r color marbling)
+ | Unclick p -> main (add_drop p r color marbling) p ()
+ | Move p -> with_drop_info (add_drop p r color marbling)
+ | Out -> with_drop_info marbling
+ in
+ with_drop_info (add_drop p r color marbling)
+
+let () = Lwt.async (main [] (400., 400.))