Loading index.html +2 −2 Changes for index.html: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ </script> </head> <body v-scope> <div class="body-content" :style="{cursor: cursor}"> <div class="body-content" :style="{cursor: fn.getCursor()}"> <h1 class="title" title="Image Viewer with Online Interactive Relighting" v-text="title"></h1> <header class="navbar" v-cloak> Loading Loading @@ -182,7 +182,7 @@ <button class="btn-dark btn-icon" :title="t('controls.fitviewh')" @click="fn.zoomFit('h')" v-icon="zoom-hfit"></button> </div> <canvas id="ivoire-display"></canvas> <canvas id="ivoire-display" :style="{cursor: fn.getCursor()}"></canvas> <progress aria-label="Downloading data" id="load-progress" class="hidden" max="100"></progress> </main> </div> Loading src/app.ts +31 −23 Changes for src/app.ts: 31 added lines, 23 removed lines. Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import { resizeCanvasToDisplaySize, SHADER_UPDATE_EVENT, shaderUpdateNotify, WebGLCanvasRenderingContext, WebGLCanvasRenderingContext } from './gl-program.ts'; import { ControlUpdateEvent, getStateDefaults, LIGHT_ANGLE_DEFAULTS, State } from './control.ts'; import { Loading @@ -19,7 +19,7 @@ import { matToString, resetMessage, roundTo, VERBOSE, VERBOSE } from './utils.ts'; import { DownloadManager } from './download.ts'; import { Dataset, MemoryDataset, SingleDataset, TiledDataset } from './dataset.ts'; Loading Loading @@ -213,6 +213,7 @@ export class App { this.setExportParams, this.onExportParamInput, this.requestRender, this.getCursor, ] as Array<(..._: any[]) => any> ) .map((m) => [m.name, m.bind(this)] as const) Loading Loading @@ -458,7 +459,7 @@ export class App { if (this.source && (this.rx.phase === 'render' || this.rx.phase === 'export')) { if (this.rx.phase === 'export') { const margin = (App.EXPORT_WINDOW_GRAB_MARGIN / Math.min(this.state.viewport.zoom, 1)), const margin = App.EXPORT_WINDOW_GRAB_MARGIN / Math.min(this.state.viewport.zoom, 1), area = this.rx.raw().exportParams.area, innerW = Math.max(margin / 4, area.w - margin), innerH = Math.max(margin / 4, area.h - margin); Loading Loading @@ -729,26 +730,34 @@ export class App { dim = DIMS.indexOf(parts[1]), lockDim = DIMS.indexOf(this.rx.exportParams.lockedDim); if (dim === -1 || lockDim === -1 || dim === lockDim) throw new Error(); if (lockDim === 1) { // Computing size if (lockDim === 1) { // Computing size const size = area.wh[ax]; if (dim === 0) { // Input start if (dim === 0) { // Input start end[ax] = clamp(val + size, size, total[ax]); start[ax] = end[ax] - size; } else { // Input end } else { // Input end start[ax] = clamp(val - size, 0, total[ax] - size); end[ax] = start[ax] + size; } } else if (dim === 1) { // Input size if (lockDim === 0) { // Computing end } else if (dim === 1) { // Input size if (lockDim === 0) { // Computing end end[ax] = clamp(start[ax] + val, start[ax] + 1, total[ax]); } else { // Computing start } else { // Computing start start[ax] = clamp(end[ax] - val, 0, end[ax] - 1); } } else { if (dim === 0) { // Input start if (dim === 0) { // Input start start[ax] = clamp(val, 0, total[ax] - 1); end[ax] = clamp(end[ax], start[ax] + 1, total[ax]); } else { // Input end } else { // Input end end[ax] = clamp(val, 1, total[ax]); start[ax] = clamp(start[ax], 0, end[ax] - 1); } Loading Loading @@ -913,15 +922,16 @@ export class App { } } private getQuadrantCursor(xy: [0 | 1 | 2, 0 | 1 | 2] | null): string | null { private getCursor(): string | null { const { exportWindowHover: xy, dragging } = this.rx.state.pointerState; return ( xy && [ ['sw-resize', 'w-resize', 'nw-resize'], ['s-resize', 'move', 'n-resize'], ['se-resize', 'e-resize', 'ne-resize'], ['nesw-resize', 'ew-resize', 'nwse-resize'], ['ns-resize', null, 'ns-resize'], ['nwse-resize', 'ew-resize', 'nesw-resize'], ][xy[0]][xy[1]] ); ) || (dragging ? 'grabbing' : null); } private bindPointerEvents() { Loading Loading @@ -991,7 +1001,7 @@ export class App { const highlight = DEBUG ? () => { if (!ev.shiftKey || !(ev.buttons & 1) || !this.source || this.rx.phase !== "render") return false; if (!ev.shiftKey || !(ev.buttons & 1) || !this.source || this.rx.phase !== 'render') return false; const texCoord = viewport.screenToTexture(evpos); let changed = false; const highlighted = []; Loading Loading @@ -1028,14 +1038,14 @@ export class App { viewport.zoomAround(Math.pow(SCROLL_FACTOR, delta), evpos); } } else if (ev.type === 'pointerdown') { if (pointerState.dragging || !ev.isPrimary || ev.button !== 0) return; if (pointerState.dragging || !ev.isPrimary || (ev.button !== 0 && ev.button !== 1)) return console.debug(ev); if (!highlight()) { pointerState.dragging = true; const texPos = viewport.screenToTexture(evpos); pointerState.overLightball = lightball; pointerState.origin = texPos; pointerState.exportWindowHover = exportWindowPart(texPos); this.rx.cursor = this.getQuadrantCursor(pointerState.exportWindowHover); pointerState.exportWindowHover = (ev.button === 0 && exportWindowPart(texPos)) || null; if (pointerState.exportWindowHover) { let [x, y]: [0 | 1 | 2, 0 | 1 | 2] = pointerState.exportWindowHover; vec2.sub( Loading @@ -1049,13 +1059,12 @@ export class App { window.addEventListener('wheel', onPointerEvent, { passive: false }); } } else if (ev.type === 'pointerup' || ev.type === 'pointerleave') { if (!pointerState.dragging || !ev.isPrimary || ev.button !== 0) return; if (!pointerState.dragging || !ev.isPrimary || (ev.button !== 0 && ev.button !== 1)) return; lastMoveEvent = null; doUpdate(); pointerState.overLightball = lightball; pointerState.dragging = false; pointerState.exportWindowHover = exportWindowPart(viewport.screenToTexture(evpos)); this.rx.cursor = this.getQuadrantCursor(pointerState.exportWindowHover); canvas.setPointerCapture(ev.pointerId); window.removeEventListener('wheel', onPointerEvent); } else if (ev.type === 'pointermove') Loading @@ -1067,7 +1076,6 @@ export class App { const windowPart = exportWindowPart(viewport.screenToTexture(evpos)); if (!arraysEq(windowPart, pointerState.exportWindowHover)) { pointerState.exportWindowHover = windowPart; this.rx.cursor = this.getQuadrantCursor(windowPart); this.requestRender(); } if (lightball !== pointerState.overLightball) { Loading src/style.sass +1 −0 Changes for src/style.sass: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ body width: 100% height: 100% box-sizing: border-box cursor: grab #load-progress position: absolute Loading Loading
index.html +2 −2 Changes for index.html: 2 added lines, 2 removed lines. Original line number Diff line number Diff line Loading @@ -11,7 +11,7 @@ </script> </head> <body v-scope> <div class="body-content" :style="{cursor: cursor}"> <div class="body-content" :style="{cursor: fn.getCursor()}"> <h1 class="title" title="Image Viewer with Online Interactive Relighting" v-text="title"></h1> <header class="navbar" v-cloak> Loading Loading @@ -182,7 +182,7 @@ <button class="btn-dark btn-icon" :title="t('controls.fitviewh')" @click="fn.zoomFit('h')" v-icon="zoom-hfit"></button> </div> <canvas id="ivoire-display"></canvas> <canvas id="ivoire-display" :style="{cursor: fn.getCursor()}"></canvas> <progress aria-label="Downloading data" id="load-progress" class="hidden" max="100"></progress> </main> </div> Loading
src/app.ts +31 −23 Changes for src/app.ts: 31 added lines, 23 removed lines. Original line number Diff line number Diff line Loading @@ -6,7 +6,7 @@ import { resizeCanvasToDisplaySize, SHADER_UPDATE_EVENT, shaderUpdateNotify, WebGLCanvasRenderingContext, WebGLCanvasRenderingContext } from './gl-program.ts'; import { ControlUpdateEvent, getStateDefaults, LIGHT_ANGLE_DEFAULTS, State } from './control.ts'; import { Loading @@ -19,7 +19,7 @@ import { matToString, resetMessage, roundTo, VERBOSE, VERBOSE } from './utils.ts'; import { DownloadManager } from './download.ts'; import { Dataset, MemoryDataset, SingleDataset, TiledDataset } from './dataset.ts'; Loading Loading @@ -213,6 +213,7 @@ export class App { this.setExportParams, this.onExportParamInput, this.requestRender, this.getCursor, ] as Array<(..._: any[]) => any> ) .map((m) => [m.name, m.bind(this)] as const) Loading Loading @@ -458,7 +459,7 @@ export class App { if (this.source && (this.rx.phase === 'render' || this.rx.phase === 'export')) { if (this.rx.phase === 'export') { const margin = (App.EXPORT_WINDOW_GRAB_MARGIN / Math.min(this.state.viewport.zoom, 1)), const margin = App.EXPORT_WINDOW_GRAB_MARGIN / Math.min(this.state.viewport.zoom, 1), area = this.rx.raw().exportParams.area, innerW = Math.max(margin / 4, area.w - margin), innerH = Math.max(margin / 4, area.h - margin); Loading Loading @@ -729,26 +730,34 @@ export class App { dim = DIMS.indexOf(parts[1]), lockDim = DIMS.indexOf(this.rx.exportParams.lockedDim); if (dim === -1 || lockDim === -1 || dim === lockDim) throw new Error(); if (lockDim === 1) { // Computing size if (lockDim === 1) { // Computing size const size = area.wh[ax]; if (dim === 0) { // Input start if (dim === 0) { // Input start end[ax] = clamp(val + size, size, total[ax]); start[ax] = end[ax] - size; } else { // Input end } else { // Input end start[ax] = clamp(val - size, 0, total[ax] - size); end[ax] = start[ax] + size; } } else if (dim === 1) { // Input size if (lockDim === 0) { // Computing end } else if (dim === 1) { // Input size if (lockDim === 0) { // Computing end end[ax] = clamp(start[ax] + val, start[ax] + 1, total[ax]); } else { // Computing start } else { // Computing start start[ax] = clamp(end[ax] - val, 0, end[ax] - 1); } } else { if (dim === 0) { // Input start if (dim === 0) { // Input start start[ax] = clamp(val, 0, total[ax] - 1); end[ax] = clamp(end[ax], start[ax] + 1, total[ax]); } else { // Input end } else { // Input end end[ax] = clamp(val, 1, total[ax]); start[ax] = clamp(start[ax], 0, end[ax] - 1); } Loading Loading @@ -913,15 +922,16 @@ export class App { } } private getQuadrantCursor(xy: [0 | 1 | 2, 0 | 1 | 2] | null): string | null { private getCursor(): string | null { const { exportWindowHover: xy, dragging } = this.rx.state.pointerState; return ( xy && [ ['sw-resize', 'w-resize', 'nw-resize'], ['s-resize', 'move', 'n-resize'], ['se-resize', 'e-resize', 'ne-resize'], ['nesw-resize', 'ew-resize', 'nwse-resize'], ['ns-resize', null, 'ns-resize'], ['nwse-resize', 'ew-resize', 'nesw-resize'], ][xy[0]][xy[1]] ); ) || (dragging ? 'grabbing' : null); } private bindPointerEvents() { Loading Loading @@ -991,7 +1001,7 @@ export class App { const highlight = DEBUG ? () => { if (!ev.shiftKey || !(ev.buttons & 1) || !this.source || this.rx.phase !== "render") return false; if (!ev.shiftKey || !(ev.buttons & 1) || !this.source || this.rx.phase !== 'render') return false; const texCoord = viewport.screenToTexture(evpos); let changed = false; const highlighted = []; Loading Loading @@ -1028,14 +1038,14 @@ export class App { viewport.zoomAround(Math.pow(SCROLL_FACTOR, delta), evpos); } } else if (ev.type === 'pointerdown') { if (pointerState.dragging || !ev.isPrimary || ev.button !== 0) return; if (pointerState.dragging || !ev.isPrimary || (ev.button !== 0 && ev.button !== 1)) return console.debug(ev); if (!highlight()) { pointerState.dragging = true; const texPos = viewport.screenToTexture(evpos); pointerState.overLightball = lightball; pointerState.origin = texPos; pointerState.exportWindowHover = exportWindowPart(texPos); this.rx.cursor = this.getQuadrantCursor(pointerState.exportWindowHover); pointerState.exportWindowHover = (ev.button === 0 && exportWindowPart(texPos)) || null; if (pointerState.exportWindowHover) { let [x, y]: [0 | 1 | 2, 0 | 1 | 2] = pointerState.exportWindowHover; vec2.sub( Loading @@ -1049,13 +1059,12 @@ export class App { window.addEventListener('wheel', onPointerEvent, { passive: false }); } } else if (ev.type === 'pointerup' || ev.type === 'pointerleave') { if (!pointerState.dragging || !ev.isPrimary || ev.button !== 0) return; if (!pointerState.dragging || !ev.isPrimary || (ev.button !== 0 && ev.button !== 1)) return; lastMoveEvent = null; doUpdate(); pointerState.overLightball = lightball; pointerState.dragging = false; pointerState.exportWindowHover = exportWindowPart(viewport.screenToTexture(evpos)); this.rx.cursor = this.getQuadrantCursor(pointerState.exportWindowHover); canvas.setPointerCapture(ev.pointerId); window.removeEventListener('wheel', onPointerEvent); } else if (ev.type === 'pointermove') Loading @@ -1067,7 +1076,6 @@ export class App { const windowPart = exportWindowPart(viewport.screenToTexture(evpos)); if (!arraysEq(windowPart, pointerState.exportWindowHover)) { pointerState.exportWindowHover = windowPart; this.rx.cursor = this.getQuadrantCursor(windowPart); this.requestRender(); } if (lightball !== pointerState.overLightball) { Loading
src/style.sass +1 −0 Changes for src/style.sass: 1 added line, 0 removed lines. Original line number Diff line number Diff line Loading @@ -69,6 +69,7 @@ body width: 100% height: 100% box-sizing: border-box cursor: grab #load-progress position: absolute Loading