125 lines
3.4 KiB
JavaScript
125 lines
3.4 KiB
JavaScript
export const LetterBoxType = {
|
|
Vertical: 0,
|
|
Horizontal: 1
|
|
};
|
|
|
|
export class PointerCorrector {
|
|
/**
|
|
* @param {Number} videoWidth
|
|
* @param {Number} videoHeight
|
|
* @param {HTMLVideoElement} videoElem
|
|
*/
|
|
constructor(videoWidth, videoHeight, videoElem) {
|
|
this.reset(videoWidth, videoHeight, videoElem);
|
|
}
|
|
|
|
/**
|
|
* @param {Number[]} position MouseEvent.clientX, MouseEvent.clientY
|
|
* @returns {Number[]}
|
|
*/
|
|
map(position) {
|
|
var rect = this._videoElem.getBoundingClientRect();
|
|
const _position = new Array(2);
|
|
|
|
// (1) set origin point to zero
|
|
_position[0] = position[0] - rect.left;
|
|
_position[1] = position[1] - rect.top;
|
|
|
|
// (2) translate Unity coordinate system (reverse y-axis)
|
|
_position[1] = rect.height - _position[1];
|
|
|
|
// (3) add offset of letterbox
|
|
_position[0] -= this._contentRect.x;
|
|
_position[1] -= this._contentRect.y;
|
|
|
|
// (4) mapping element rectangle to video rectangle
|
|
_position[0] = _position[0] / this._contentRect.width * this._videoWidth;
|
|
_position[1] = _position[1] / this._contentRect.height * this._videoHeight;
|
|
|
|
return _position;
|
|
}
|
|
|
|
/**
|
|
* @param {Number} videoWidth
|
|
*/
|
|
setVideoWidth(videoWidth) {
|
|
this._videoWidth = videoWidth;
|
|
this._reset();
|
|
}
|
|
|
|
/**
|
|
* @param {Number} videoHeight
|
|
*/
|
|
setVideoHeight(videoHeight) {
|
|
this._videoHeight = videoHeight;
|
|
this._reset();
|
|
}
|
|
|
|
/**
|
|
* @param {HTMLVideoElement} videoElem
|
|
*/
|
|
setRect(videoElem) {
|
|
this._videoElem = videoElem;
|
|
this._reset();
|
|
}
|
|
|
|
/**
|
|
* @param {Number} videoWidth
|
|
* @param {Number} videoHeight
|
|
* @param {HTMLVideoElement} videoElem
|
|
*/
|
|
reset(videoWidth, videoHeight, videoElem) {
|
|
this._videoWidth = videoWidth;
|
|
this._videoHeight = videoHeight;
|
|
this._videoElem = videoElem;
|
|
this._reset();
|
|
}
|
|
|
|
get letterBoxType() {
|
|
const videoRatio = this._videoHeight / this._videoWidth;
|
|
var rect = this._videoElem.getBoundingClientRect();
|
|
const rectRatio = rect.height / rect.width;
|
|
return videoRatio > rectRatio ? LetterBoxType.Vertical : LetterBoxType.Horizontal;
|
|
}
|
|
|
|
get letterBoxSize() {
|
|
var rect = this._videoElem.getBoundingClientRect();
|
|
switch(this.letterBoxType) {
|
|
case LetterBoxType.Horizontal: {
|
|
const ratioWidth = rect.width / this._videoWidth;
|
|
const height = this._videoHeight * ratioWidth;
|
|
return (rect.height - height) * 0.5;
|
|
}
|
|
case LetterBoxType.Vertical: {
|
|
const ratioHeight = rect.height / this._videoHeight;
|
|
const width = this._videoWidth * ratioHeight;
|
|
return (rect.width - width) * 0.5;
|
|
}
|
|
}
|
|
throw 'invalid status';
|
|
}
|
|
|
|
/**
|
|
* Returns rectangle for displaying video with the origin at the left-top of the element.
|
|
* Not considered applying CSS like `object-fit`.
|
|
* @returns {Object}
|
|
*/
|
|
get contentRect() {
|
|
const letterBoxType = this.letterBoxType;
|
|
const letterBoxSize = this.letterBoxSize;
|
|
|
|
var rect = this._videoElem.getBoundingClientRect();
|
|
|
|
const x = letterBoxType == LetterBoxType.Vertical ? letterBoxSize : 0;
|
|
const y = letterBoxType == LetterBoxType.Horizontal ? letterBoxSize : 0;
|
|
const width = letterBoxType == LetterBoxType.Vertical ? rect.width - letterBoxSize * 2 : rect.width;
|
|
const height = letterBoxType == LetterBoxType.Horizontal ? rect.height - letterBoxSize * 2 : rect.height;
|
|
|
|
return {x: x, y: y, width: width, height: height};
|
|
}
|
|
|
|
_reset() {
|
|
this._contentRect = this.contentRect;
|
|
}
|
|
}
|