Adding support for mouse wheel events. cleaning up click handler to take functions
This commit is contained in:
parent
85451d24fb
commit
1961ac6249
6 changed files with 108 additions and 60 deletions
49
src/ui.ts
49
src/ui.ts
|
|
@ -4,12 +4,13 @@ export type UIValue =
|
|||
| { kind: 'text', content: string, color?: string }
|
||||
| { kind: 'row', children: UIValue[], gap: number }
|
||||
| { kind: 'column', children: UIValue[], gap: number }
|
||||
| { kind: 'clickable', child: UIValue, event: any }
|
||||
| { kind: 'padding', child: UIValue, amount: number }
|
||||
| { kind: 'positioned', x: number, y: number, child: UIValue }
|
||||
| { kind: 'opacity', child: UIValue, opacity: number }
|
||||
| { kind: 'clip', child: UIValue, w: number, h: number }
|
||||
| { kind: 'stack', children: UIValue[] }
|
||||
| { kind: 'clickable', child: UIValue, onClick: any }
|
||||
| { kind: 'scrollable', child: UIValue, w: number, h: number, scrollX: number, scrollY: number, onScroll: any }
|
||||
| { kind: 'stateful', key: string, focusable: boolean, init: any, update: any, view: any }
|
||||
|
||||
type ClickRegion = {
|
||||
|
|
@ -17,11 +18,21 @@ type ClickRegion = {
|
|||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
event: any;
|
||||
onClick: any;
|
||||
};
|
||||
|
||||
let clickRegions: ClickRegion[] = [];
|
||||
|
||||
type ScrollRegion = {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
onScroll: any;
|
||||
};
|
||||
|
||||
let scrollRegions: ScrollRegion[] = [];
|
||||
|
||||
export function render(ui: UIValue, canvas: HTMLCanvasElement) {
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (ctx) {
|
||||
|
|
@ -32,6 +43,7 @@ export function render(ui: UIValue, canvas: HTMLCanvasElement) {
|
|||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
||||
|
||||
clickRegions = [];
|
||||
scrollRegions = [];
|
||||
renderUI(ui, ctx, 0, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -88,7 +100,7 @@ function renderUI(ui: UIValue, ctx: CanvasRenderingContext2D, x: number, y: numb
|
|||
case 'row': {
|
||||
let offsetX = 0;
|
||||
for (const child of ui.children) {
|
||||
const size = measure(child);
|
||||
// const size = measure(child);
|
||||
renderUI(child, ctx, x + offsetX, y);
|
||||
offsetX += measure(child).width + (ui.gap || 0);
|
||||
}
|
||||
|
|
@ -106,11 +118,22 @@ function renderUI(ui: UIValue, ctx: CanvasRenderingContext2D, x: number, y: numb
|
|||
|
||||
case 'clickable': {
|
||||
const size = measure(ui.child);
|
||||
clickRegions.push({ x, y, width: size.width, height: size.height, event: ui.event })
|
||||
clickRegions.push({ x, y, width: size.width, height: size.height, onClick: ui.onClick })
|
||||
renderUI(ui.child, ctx, x, y);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'scrollable': {
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.rect(x, y, ui.w, ui.h);
|
||||
ctx.clip();
|
||||
renderUI(ui.child, ctx, x - ui.scrollX, y - ui.scrollY);
|
||||
ctx.restore();
|
||||
scrollRegions.push({ x, y, width: ui.w, height: ui.h, onScroll: ui.onScroll })
|
||||
break;
|
||||
}
|
||||
|
||||
case 'padding':
|
||||
renderUI(ui.child, ctx, x + ui.amount, y + ui.amount);
|
||||
break;
|
||||
|
|
@ -187,6 +210,9 @@ export function _measure(ui: UIValue): { width: number, height: number } {
|
|||
case 'clickable':
|
||||
return measure(ui.child);
|
||||
|
||||
case 'scrollable':
|
||||
return { width: ui.w, height: ui.h };
|
||||
|
||||
case 'opacity':
|
||||
return measure(ui.child);
|
||||
|
||||
|
|
@ -223,14 +249,14 @@ export function _measure(ui: UIValue): { width: number, height: number } {
|
|||
}
|
||||
}
|
||||
|
||||
export function hitTest(x: number, y: number): { event: any, relativeX: number, relativeY: number } | null {
|
||||
export function hitTest(x: number, y: number): { onClick: any, relativeX: number, relativeY: number } | null {
|
||||
for (let i = clickRegions.length - 1; i >= 0; i--) {
|
||||
const region = clickRegions[i];
|
||||
|
||||
if (x >= region.x && x < region.x + region.width &&
|
||||
y >= region.y && y < region.y + region.height) {
|
||||
return {
|
||||
event: region.event,
|
||||
onClick: region.onClick,
|
||||
relativeX: x - region.x,
|
||||
relativeY: y - region.y,
|
||||
};
|
||||
|
|
@ -238,3 +264,14 @@ export function hitTest(x: number, y: number): { event: any, relativeX: number,
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function scrollHitTest(x: number, y: number): { onScroll: any } | null {
|
||||
for (let i = scrollRegions.length - 1; i >= 0; i--) {
|
||||
const region = scrollRegions[i];
|
||||
if (x >= region.x && x < region.x + region.width &&
|
||||
y >= region.y && y < region.y + region.height) {
|
||||
return { onScroll: region.onScroll };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue