@readium/navigator
Version:
Next generation SDK for publications in Web Apps
152 lines (139 loc) • 5.59 kB
text/typescript
import { sML } from "../../helpers/sML";
export interface Point {
X: number;
Y: number;
}
export enum HorizontalThird {
Left,
Center,
Right
}
export enum VerticalThird {
Top,
Middle,
Bottom
}
export interface NinthPoint {
X: HorizontalThird | null;
Y: VerticalThird | null;
}
export interface BibiEvent {
Target: EventTarget | null;
Coord: Point | null;
Ratio: Point | null;
Division: NinthPoint | null;
}
export class FXLCoordinator {
HTML: HTMLElement;
Head: HTMLHeadElement;
Body: HTMLElement;
constructor() {
this.HTML = document.documentElement;
this.Head = document.head;
this.Body = document.body;
}
/*
getElementCoord(El: any) {
var Coord = { X: El["offsetLeft"], Y: El["offsetTop"] };
while(El.offsetParent) El = El.offsetParent, Coord.X += El["offsetLeft"], Coord.Y += El["offsetTop"];
return Coord;
}
*/
private outerWidth = 0;
private outerHeight = 0;
refreshOuterPixels(_: DOMRect) {
if(sML.OS.iOS) return; // No need on iOS
this.outerHeight = window.outerHeight - window.innerHeight;
if(sML.OS.Android && sML.UA.Chrome) {
if(window.screen.height > window.innerHeight)
// This is a hack: since outer/inner are zero, we assume there's a
// top (chrome url bar) and bottom (android controls) bar and divide
// by 1.5 because the top bar is roughtly 2x height of the bottom one
this.outerHeight = (window.screen.height - window.innerHeight) / 1.5;
}
this.outerWidth = window.outerWidth - window.innerWidth;
}
getBibiEventCoord(Eve: TouchEvent | MouseEvent, touch=0): Point {
const Coord: Point = { X:0, Y:0 };
if(/^touch/.test(Eve.type)) {
Coord.X = (Eve as TouchEvent).touches[touch].screenX;
Coord.Y = (Eve as TouchEvent).touches[touch].screenY;
} else {
Coord.X = (Eve as MouseEvent).screenX;
Coord.Y = (Eve as MouseEvent).screenY;
}
if(((Eve.target as HTMLElement).ownerDocument?.documentElement || (Eve.target as HTMLDocument).documentElement) === this.HTML) {
Coord.X -= (this.HTML.scrollLeft + this.Body.scrollLeft);
Coord.Y -= (this.HTML.scrollTop + this.Body.scrollTop);
} else {
/*
var Item = Eve.target.ownerDocument.documentElement.Item;
ItemCoord = this.getElementCoord(Item);
if(!Item.PrePaginated && !Item.Outsourcing) ItemCoord.X += settings.S["item-padding-left"], ItemCoord.Y += settings.S["item-padding-top"];
Coord.X = (Coord.X + ItemCoord.X - R.Main.scrollLeft) * R.Main.Transformation.Scale + R.Main.Transformation.Translation.X;
Coord.Y = (Coord.Y + ItemCoord.Y - R.Main.scrollTop ) * R.Main.Transformation.Scale + R.Main.Transformation.Translation.Y;
*/
}
Coord.X -= this.outerWidth;
Coord.Y -= this.outerHeight;
return Coord;
}
getTouchDistance(Eve: TouchEvent) {
if (Eve.touches.length !== 2) return 0;
const x1 = Eve.touches[0].screenX - this.outerWidth;
const y1 = Eve.touches[0].screenY - this.outerHeight;
const x2 = Eve.touches[1].screenX - this.outerWidth;
const y2 = Eve.touches[1].screenY - this.outerHeight;
return Math.sqrt((Math.pow((x2 - x1), 2)) + (Math.pow((y2 - y1), 2)));
}
getTouchCenter(Eve: TouchEvent): Point | null {
if (Eve.touches.length !== 2) return null;
const subL = (this.HTML.scrollLeft + this.Body.scrollLeft);
const subT = (this.HTML.scrollTop + this.Body.scrollTop);
const x1 = Eve.touches[0].screenX - this.outerWidth - subL;
const y1 = Eve.touches[0].screenY - this.outerHeight - subT;
const x2 = Eve.touches[1].screenX - this.outerWidth - subL;
const y2 = Eve.touches[1].screenY - this.outerHeight - subT;
return { X: (x1 + x2) / 2, Y: (y1 + y2) / 2 };
}
getBibiEvent(Eve: Event): BibiEvent {
if(!Eve) return {
Coord: null,
Division: null,
Ratio: null,
Target: null
};
const Coord = this.getBibiEventCoord(Eve as TouchEvent | MouseEvent);
let FlipperWidth = 0.3; // TODO flipper-width
const Ratio = {
X: Coord.X / window.innerWidth,
Y: Coord.Y / window.innerHeight
};
let BorderT, BorderB, BorderL, BorderR;
if(FlipperWidth < 1) { // Ratio
BorderL = BorderT = FlipperWidth;
BorderR = BorderB = 1 - FlipperWidth;
} else { // Pixel to Ratio
BorderL = FlipperWidth / window.innerWidth;
BorderT = FlipperWidth / window.innerHeight;
BorderR = 1 - BorderL;
BorderB = 1 - BorderT;
}
const Division: NinthPoint = {
X: null,
Y: null
};
if(Ratio.X < BorderL) Division.X = HorizontalThird.Left;
else if(BorderR < Ratio.X) Division.X = HorizontalThird.Right;
else Division.X = HorizontalThird.Center;
if(Ratio.Y < BorderT) Division.Y = VerticalThird.Top;
else if(BorderB < Ratio.Y) Division.Y = VerticalThird.Bottom;
else Division.Y = VerticalThird.Middle;
return {
Target: Eve.target,
Coord: Coord,
Ratio: Ratio,
Division: Division
};
}
}