spiegel-keyman/common/web/gesture-recognizer/src/paddedZoneSource.ts

110 lines
No EOL
3.8 KiB
TypeScript

import { RecognitionZoneSource } from "./recognitionZoneSource.js";
import { ViewportZoneSource } from "./viewportZoneSource.js";
export class PaddedZoneSource implements RecognitionZoneSource {
private readonly root: RecognitionZoneSource;
private edgePadding: {
x: number,
y: number,
w: number,
h: number
};
/**
* Provides a dynamic 'padded' recognition zone based upon offsetting from the borders
* of the active page's viewport.
*
* Padding is defined using the standard CSS border & padding spec style:
* - [a]: equal and even padding on all sides
* - [a, b]: top & bottom use `a`, left & right use `b`
* - [a, b, c]: top uses `a`, left & right use `b`, bottom uses `c`
* - [a, b, c, d]: top, right, bottom, then left.
*
* Positive padding reduces the size of the resulting zone; negative padding expands it.
*
* @param rootZoneSource The root zone source object/element to be 'padded'
* @param edgePadding A set of 1 to 4 numbers defining padding per the standard CSS border & padding spec style.
*/
public constructor(...edgePadding: number[])
/**
* Provides a dynamic 'padded' recognition zone based upon offsetting from the borders
* of another defined zone.
*
* Padding is defined using the standard CSS border & padding spec style:
* - [a]: equal and even padding on all sides
* - [a, b]: top & bottom use `a`, left & right use `b`
* - [a, b, c]: top uses `a`, left & right use `b`, bottom uses `c`
* - [a, b, c, d]: top, right, bottom, then left.
*
* Positive padding reduces the size of the resulting zone; negative padding expands it.
*
* @param rootZoneSource The root zone source object/element to be 'padded'
* @param edgePadding A set of 1 to 4 numbers defining padding per the standard CSS border & padding spec style.
*/
public constructor(rootZoneSource: RecognitionZoneSource, ...edgePadding: number[]);
public constructor(rootZoneSource: RecognitionZoneSource | number, ...edgePadding: number[]) {
// Disambiguate which constructor style was intended.
if(typeof rootZoneSource == 'number') {
edgePadding = [rootZoneSource, ...edgePadding];
rootZoneSource = new ViewportZoneSource();
}
this.root = rootZoneSource;
// In case it isn't yet defined.
edgePadding = edgePadding || [0, 0, 0, 0];
// Modeled after CSS styling definitions... just with preprocessed numbers, not strings.
switch(edgePadding.length) {
case 1:
// all sides equal
const val = edgePadding[0];
this.edgePadding = {
x: val,
y: val,
w: 2 * val,
h: 2 * val
};
break;
case 2:
// top & bottom, left & right
this.edgePadding = {
x: edgePadding[1],
y: edgePadding[0],
w: 2 * edgePadding[1],
h: 2 * edgePadding[0]
};
break;
case 3:
// top, left & right, bottom
this.edgePadding = {
x: edgePadding[1],
y: edgePadding[0],
w: 2 * edgePadding[1],
h: edgePadding[0] + edgePadding[2]
};
case 4:
// top, right, bottom, left
this.edgePadding = {
x: edgePadding[3],
y: edgePadding[0],
w: edgePadding[1] + edgePadding[3],
h: edgePadding[0] + edgePadding[2]
}
break;
default:
throw new Error("Invalid values for PaddedZoneSource's edgePadding - must be between 1 to 4 `number` values.");
}
}
getBoundingClientRect(): DOMRect {
const rootZone = this.root.getBoundingClientRect();
return DOMRect.fromRect({
x: rootZone.x + this.edgePadding.x,
y: rootZone.y + this.edgePadding.y,
width: rootZone.width - this.edgePadding.w,
height: rootZone.height - this.edgePadding.h
});
}
}