Initial commit
This commit is contained in:
commit
a6272848f9
379 changed files with 74829 additions and 0 deletions
271
build/dev/javascript/paint/impl_canvas_bindings.mjs
Normal file
271
build/dev/javascript/paint/impl_canvas_bindings.mjs
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
import { Ok, Error } from "./gleam.mjs";
|
||||
|
||||
class PaintCanvas extends HTMLElement {
|
||||
// Open an issue if you are in need of any other attributes :)
|
||||
static observedAttributes = ["width", "height", "style", "picture"];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// Create a canvas
|
||||
this.canvas = document.createElement("canvas");
|
||||
const style = document.createElement("style");
|
||||
style.textContent = `
|
||||
:host {
|
||||
display: inline-block;
|
||||
}
|
||||
`;
|
||||
this.shadow = this.attachShadow({ mode: "open" });
|
||||
this.shadow.appendChild(style);
|
||||
this.shadow.appendChild(this.canvas);
|
||||
this.ctx = this.canvas.getContext("2d");
|
||||
}
|
||||
|
||||
attributeChangedCallback(name, _oldValue, newValue) {
|
||||
if (name === "picture") {
|
||||
this.picture = newValue;
|
||||
return;
|
||||
} else if (name === "width") {
|
||||
this.width = newValue;
|
||||
} else if (name === "height") {
|
||||
this.height = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
drawPicture() {
|
||||
if (!this.pictureString) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.ctx.reset();
|
||||
const display =
|
||||
window.PAINT_STATE[
|
||||
"display_on_rendering_context_with_default_drawing_state"
|
||||
];
|
||||
|
||||
display(this.pictureString, this.ctx);
|
||||
}
|
||||
|
||||
set picture(value) {
|
||||
this.pictureString = value;
|
||||
this.drawPicture();
|
||||
}
|
||||
|
||||
set width(value) {
|
||||
this.canvas.width = value;
|
||||
this.drawPicture();
|
||||
}
|
||||
|
||||
set height(value) {
|
||||
this.canvas.height = value;
|
||||
this.drawPicture();
|
||||
}
|
||||
|
||||
get width() {
|
||||
return this.canvas.width;
|
||||
}
|
||||
|
||||
get height() {
|
||||
return this.canvas.height;
|
||||
}
|
||||
}
|
||||
|
||||
export function define_web_component() {
|
||||
window.customElements.define("paint-canvas", PaintCanvas);
|
||||
}
|
||||
|
||||
export function get_rendering_context(selector) {
|
||||
// TODO: Handle the case where the canvas element is not found.
|
||||
return document.querySelector(selector).getContext("2d");
|
||||
}
|
||||
|
||||
export function setup_request_animation_frame(callback) {
|
||||
window.requestAnimationFrame((time) => {
|
||||
callback(time);
|
||||
});
|
||||
}
|
||||
|
||||
export function setup_input_handler(event_name, callback) {
|
||||
window.addEventListener(event_name, callback);
|
||||
}
|
||||
|
||||
export function get_key_code(event) {
|
||||
return event.keyCode;
|
||||
}
|
||||
|
||||
export function set_global(state, id) {
|
||||
if (typeof window.PAINT_STATE == "undefined") {
|
||||
window.PAINT_STATE = {};
|
||||
}
|
||||
window.PAINT_STATE[id] = state;
|
||||
}
|
||||
|
||||
export function get_global(id) {
|
||||
if (!window.PAINT_STATE) {
|
||||
return new Error(undefined);
|
||||
}
|
||||
if (!(id in window.PAINT_STATE)) {
|
||||
return new Error(undefined);
|
||||
}
|
||||
return new Ok(window.PAINT_STATE[id]);
|
||||
}
|
||||
|
||||
export function get_width(ctx) {
|
||||
return ctx.canvas.clientWidth;
|
||||
}
|
||||
|
||||
export function get_height(ctx) {
|
||||
return ctx.canvas.clientHeight;
|
||||
}
|
||||
|
||||
// Based on https://stackoverflow.com/questions/17130395/real-mouse-position-in-canvas
|
||||
export function mouse_pos(ctx, event) {
|
||||
// Calculate the scaling of the canvas vs its content
|
||||
const rect = ctx.canvas.getBoundingClientRect();
|
||||
const scaleX = ctx.canvas.width / rect.width;
|
||||
const scaleY = ctx.canvas.height / rect.height;
|
||||
|
||||
return [
|
||||
(event.clientX - rect.left) * scaleX,
|
||||
(event.clientY - rect.top) * scaleY,
|
||||
];
|
||||
}
|
||||
|
||||
// if check_pressed is true, the function will return true if the button was pressed
|
||||
// if check_pressed is false, the function will return true if the button was released
|
||||
export function check_mouse_button(
|
||||
event,
|
||||
previous_event,
|
||||
button_index,
|
||||
check_pressed,
|
||||
) {
|
||||
let previous_buttons = previous_event?.buttons ?? 0;
|
||||
let current_buttons = event.buttons;
|
||||
|
||||
// ~001 &&
|
||||
// 011
|
||||
// -----
|
||||
// 010 found the newly pressed!
|
||||
//
|
||||
// 011 &&
|
||||
// ~001
|
||||
// -----
|
||||
// 010 found the newly released!
|
||||
if (check_pressed) {
|
||||
previous_buttons = ~previous_buttons;
|
||||
} else {
|
||||
current_buttons = ~current_buttons;
|
||||
}
|
||||
|
||||
let button = previous_buttons & current_buttons & (1 << button_index);
|
||||
return !!button;
|
||||
}
|
||||
|
||||
export function reset(ctx) {
|
||||
ctx.reset();
|
||||
}
|
||||
|
||||
export function arc(ctx, radius, start, end, fill, stroke) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, radius, start, end);
|
||||
if (fill) {
|
||||
ctx.fill();
|
||||
}
|
||||
if (stroke) {
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
export function polygon(ctx, points, closed, fill, stroke) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(0, 0);
|
||||
let started = false;
|
||||
for (const point of points) {
|
||||
let x = point[0];
|
||||
let y = point[1];
|
||||
if (started) {
|
||||
ctx.lineTo(x, y);
|
||||
} else {
|
||||
ctx.moveTo(x, y);
|
||||
started = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (closed) {
|
||||
ctx.closePath();
|
||||
}
|
||||
|
||||
if (fill && closed) {
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
if (stroke) {
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
export function text(ctx, text, style) {
|
||||
ctx.font = style;
|
||||
ctx.fillText(text, 0, 0);
|
||||
}
|
||||
|
||||
export function save(ctx) {
|
||||
ctx.save();
|
||||
}
|
||||
|
||||
export function restore(ctx) {
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
export function set_fill_colour(ctx, css_colour) {
|
||||
ctx.fillStyle = css_colour;
|
||||
}
|
||||
|
||||
export function set_stroke_color(ctx, css_color) {
|
||||
ctx.strokeStyle = css_color;
|
||||
}
|
||||
|
||||
export function set_line_width(ctx, width) {
|
||||
ctx.lineWidth = width;
|
||||
}
|
||||
|
||||
export function translate(ctx, x, y) {
|
||||
ctx.translate(x, y);
|
||||
}
|
||||
|
||||
export function scale(ctx, x, y) {
|
||||
ctx.scale(x, y);
|
||||
}
|
||||
|
||||
export function rotate(ctx, radians) {
|
||||
ctx.rotate(radians);
|
||||
}
|
||||
|
||||
export function reset_transform(ctx) {
|
||||
ctx.resetTransform();
|
||||
}
|
||||
|
||||
export function draw_image(ctx, image, width_px, height_px) {
|
||||
ctx.drawImage(image, 0, 0, width_px, height_px);
|
||||
}
|
||||
|
||||
export function image_from_query(selector) {
|
||||
return document.querySelector(selector);
|
||||
}
|
||||
|
||||
export function image_from_src(src) {
|
||||
const image = new Image();
|
||||
image.src = src;
|
||||
return image;
|
||||
}
|
||||
|
||||
export function on_image_load(image, callback) {
|
||||
if (image.complete) {
|
||||
callback();
|
||||
} else {
|
||||
image.addEventListener("load", callback);
|
||||
}
|
||||
}
|
||||
|
||||
export function set_image_smoothing_enabled(ctx, value) {
|
||||
ctx.imageSmoothingEnabled = value;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue