trtc-electron-sdk
Version:
trtc electron sdk
502 lines (501 loc) • 25 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ResizeAnchorMode = void 0;
const logger_1 = __importDefault(require("../logger"));
var ResizeAnchorMode;
(function (ResizeAnchorMode) {
ResizeAnchorMode[ResizeAnchorMode["Both"] = 0] = "Both";
ResizeAnchorMode[ResizeAnchorMode["Corner"] = 1] = "Corner";
ResizeAnchorMode[ResizeAnchorMode["Edge"] = 2] = "Edge";
})(ResizeAnchorMode = exports.ResizeAnchorMode || (exports.ResizeAnchorMode = {}));
const ResizeAnchorCSSClass = {
topLeftAnchor: 'trtc-resizable-top-left-anchor',
topAnchor: 'trtc-resizable-top-anchor',
topRightAnchor: 'trtc-resizable-top-right-anchor',
leftAnchor: 'trtc-resizable-left-anchor',
rightAnchor: 'trtc-resizable-right-anchor',
bottomLeftAnchor: 'trtc-resizable-bottom-left-anchor',
bottomAnchor: 'trtc-resizable-bottom-anchor',
bottomRightAnchor: 'trtc-resizable-bottom-right-anchor',
};
const ResizeAnchorStyle = {
resizeAnchor: {
position: 'absolute',
width: '0.5rem',
height: '0.5rem',
border: '1px solid transparent',
backgroundColor: 'transparent'
},
topLeftAnchor: {
top: '0',
left: '0',
cursor: 'nw-resize'
},
topAnchor: {
top: '0',
left: 'calc(50% - 0.25rem)',
cursor: 'n-resize'
},
topRightAnchor: {
top: '0',
right: '0',
cursor: 'ne-resize'
},
leftAnchor: {
top: 'calc(50% - 0.25rem)',
left: '0',
cursor: 'w-resize'
},
rightAnchor: {
top: 'calc(50% - 0.25rem)',
right: '0',
cursor: 'e-resize'
},
bottomLeftAnchor: {
bottom: '0',
left: '0',
cursor: 'sw-resize'
},
bottomAnchor: {
bottom: '0',
left: 'calc(50% - 0.25rem)',
cursor: 's-resize'
},
bottomRightAnchor: {
bottom: '0',
right: '0',
cursor: 'se-resize'
}
};
function setElementStyle(el, styleOptions) {
for (const key in styleOptions) {
el.style[key] = styleOptions[key];
}
}
class Resizable {
constructor(resizeTarget, container, options = {
keepRatio: false,
stopPropagation: false,
anchorMode: ResizeAnchorMode.Both,
canExceedContainer: false
}) {
this.logPrefix = '[Resizable]';
this.container = null;
this.options = {
keepRatio: false,
stopPropagation: false,
anchorMode: ResizeAnchorMode.Both,
canExceedContainer: false
};
this.callbacksMap = new Map();
this.topLeftAnchor = null;
this.topAnchor = null;
this.topRightAnchor = null;
this.leftAnchor = null;
this.rightAnchor = null;
this.bottomLeftAnchor = null;
this.bottomAnchor = null;
this.bottomRightAnchor = null;
this.currentAnchor = null;
this.resizeStartLeft = 0;
this.resizeStartTop = 0;
this.originLeft = 0;
this.originTop = 0;
this.originWidth = 0;
this.originHeight = 0;
this.resizeTarget = resizeTarget;
this.container = container || document.body;
this.options = {
keepRatio: !!options.keepRatio || false,
stopPropagation: !!options.stopPropagation || false,
anchorMode: options.anchorMode || ResizeAnchorMode.Both,
canExceedContainer: !!options.canExceedContainer || false
};
this.mousedown = this.mousedown.bind(this);
this.mousemove = this.mousemove.bind(this);
this.mouseup = this.mouseup.bind(this);
this.currentAnchor = null;
this.createResizeAnchor();
this.resizeTarget.classList.add("trtc-resizable");
this.resizeTarget.style.position = 'absolute';
this.resizeTarget.style.overflow = 'hidden';
this.initResizeEvent();
}
createResizeAnchor() {
var _a, _b, _c, _d, _e, _f, _g, _h;
const topLeftAnchor = document.createElement("div");
topLeftAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.topLeftAnchor}`;
setElementStyle(topLeftAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.topLeftAnchor));
this.topLeftAnchor = topLeftAnchor;
const topAnchor = document.createElement("div");
topAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.topAnchor}`;
setElementStyle(topAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.topAnchor));
this.topAnchor = topAnchor;
const topRightAnchor = document.createElement("div");
topRightAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.topRightAnchor}`;
setElementStyle(topRightAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.topRightAnchor));
this.topRightAnchor = topRightAnchor;
const leftAnchor = document.createElement("div");
leftAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.leftAnchor}`;
setElementStyle(leftAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.leftAnchor));
this.leftAnchor = leftAnchor;
const rightAnchor = document.createElement("div");
rightAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.rightAnchor}`;
setElementStyle(rightAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.rightAnchor));
this.rightAnchor = rightAnchor;
const bottomLeftAnchor = document.createElement("div");
bottomLeftAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.bottomLeftAnchor}`;
setElementStyle(bottomLeftAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.bottomLeftAnchor));
this.bottomLeftAnchor = bottomLeftAnchor;
const bottomAnchor = document.createElement("div");
bottomAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.bottomAnchor}`;
setElementStyle(bottomAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.bottomAnchor));
this.bottomAnchor = bottomAnchor;
const bottomRightAnchor = document.createElement("div");
bottomRightAnchor.className = `trtc-resizable-resize-anchor ${ResizeAnchorCSSClass.bottomRightAnchor}`;
setElementStyle(bottomRightAnchor, Object.assign({}, ResizeAnchorStyle.resizeAnchor, ResizeAnchorStyle.bottomRightAnchor));
this.bottomRightAnchor = bottomRightAnchor;
if (this.options.anchorMode === ResizeAnchorMode.Both || this.options.anchorMode === ResizeAnchorMode.Edge) {
(_a = this.resizeTarget) === null || _a === void 0 ? void 0 : _a.appendChild(topAnchor);
(_b = this.resizeTarget) === null || _b === void 0 ? void 0 : _b.appendChild(leftAnchor);
(_c = this.resizeTarget) === null || _c === void 0 ? void 0 : _c.appendChild(rightAnchor);
(_d = this.resizeTarget) === null || _d === void 0 ? void 0 : _d.appendChild(bottomAnchor);
}
if (this.options.anchorMode === ResizeAnchorMode.Both || this.options.anchorMode === ResizeAnchorMode.Corner) {
(_e = this.resizeTarget) === null || _e === void 0 ? void 0 : _e.appendChild(topLeftAnchor);
(_f = this.resizeTarget) === null || _f === void 0 ? void 0 : _f.appendChild(topRightAnchor);
(_g = this.resizeTarget) === null || _g === void 0 ? void 0 : _g.appendChild(bottomLeftAnchor);
(_h = this.resizeTarget) === null || _h === void 0 ? void 0 : _h.appendChild(bottomRightAnchor);
}
}
initResizeEvent() {
var _a, _b, _c, _d, _e, _f, _g, _h;
(_a = this.topLeftAnchor) === null || _a === void 0 ? void 0 : _a.addEventListener("mousedown", this.mousedown, false);
(_b = this.topAnchor) === null || _b === void 0 ? void 0 : _b.addEventListener("mousedown", this.mousedown, false);
(_c = this.topRightAnchor) === null || _c === void 0 ? void 0 : _c.addEventListener("mousedown", this.mousedown, false);
(_d = this.leftAnchor) === null || _d === void 0 ? void 0 : _d.addEventListener("mousedown", this.mousedown, false);
(_e = this.rightAnchor) === null || _e === void 0 ? void 0 : _e.addEventListener("mousedown", this.mousedown, false);
(_f = this.bottomLeftAnchor) === null || _f === void 0 ? void 0 : _f.addEventListener("mousedown", this.mousedown, false);
(_g = this.bottomAnchor) === null || _g === void 0 ? void 0 : _g.addEventListener("mousedown", this.mousedown, false);
(_h = this.bottomRightAnchor) === null || _h === void 0 ? void 0 : _h.addEventListener("mousedown", this.mousedown, false);
}
mousedown(event) {
if (event.button !== 0) {
return;
}
event.preventDefault(); // Avoid select text content.
if (this.options.stopPropagation) {
event.stopPropagation();
}
this.currentAnchor = event.target;
this.resizeStartLeft = event.screenX;
this.resizeStartTop = event.screenY;
if (document.defaultView && this.resizeTarget) {
const resizeTargetStyle = document.defaultView.getComputedStyle(this.resizeTarget);
this.originTop = window.parseInt(resizeTargetStyle.top);
this.originLeft = window.parseInt(resizeTargetStyle.left);
this.originWidth = this.resizeTarget.offsetWidth;
this.originHeight = this.resizeTarget.offsetHeight;
logger_1.default.debug("resize origin:", this.originTop, this.originLeft, this.originWidth, this.originHeight);
}
else {
logger_1.default.error(`${this.logPrefix}mouseDown 'resizeTarget' is null`);
}
document.addEventListener("mousemove", this.mousemove, false);
document.addEventListener("mouseup", this.mouseup, false);
}
mousemove(event) {
if (!this.container || !this.resizeTarget || !this.currentAnchor) {
logger_1.default.error(`${this.logPrefix}mouseMove error. No valid inner info:`, this.container, this.resizeTarget, this.currentAnchor);
return;
}
const anchorType = this.currentAnchor.classList[1];
let left = this.originLeft, top = this.originTop, width = this.originWidth, height = this.originHeight;
let result;
switch (anchorType) {
case ResizeAnchorCSSClass.topLeftAnchor:
result = this._resizeTop(event);
top = result.top;
height = result.height;
result = this._resizeLeft(event);
left = result.left;
width = result.width;
if (this.options.keepRatio) {
if (width / this.originWidth < height / this.originHeight) {
// 宽度缩放比例小于高度缩放比例,保持当前宽度,调整高度
height = (width * this.originHeight) / this.originWidth;
// 需要调整 y 坐标
top = this.originTop + this.originHeight - height;
}
else {
// 高度缩放比例小于宽度缩放比例,保持当前高度,调整宽度
width = (height * this.originWidth) / this.originHeight;
// 需要调整 x 坐标
left = this.originLeft + this.originWidth - width;
}
}
break;
case ResizeAnchorCSSClass.topAnchor:
result = this._resizeTop(event);
top = result.top;
height = result.height;
if (this.options.keepRatio) {
width = this.originWidth * height / this.originHeight;
if (width < 20) {
width = 20;
height = this.originHeight * width / this.originWidth;
top = this.originTop + this.originHeight - height;
}
else if (!this.options.canExceedContainer && width > this.container.offsetWidth - this.originLeft) {
width = this.container.offsetWidth - this.originLeft;
height = this.originHeight * width / this.originWidth;
top = this.originTop + this.originHeight - height;
}
}
break;
case ResizeAnchorCSSClass.topRightAnchor:
result = this._resizeTop(event);
top = result.top;
height = result.height;
width = this._resizeRight(event);
if (this.options.keepRatio) {
if (width / this.originWidth < height / this.originHeight) {
height = (width * this.originHeight) / this.originWidth;
top = this.originTop + this.originHeight - height;
}
else {
width = (height * this.originWidth) / this.originHeight;
}
}
break;
case ResizeAnchorCSSClass.leftAnchor:
result = this._resizeLeft(event);
left = result.left;
width = result.width;
if (this.options.keepRatio) {
height = this.originHeight * width / this.originWidth;
if (height < 20) {
height = 20;
width = this.originWidth * height / this.originHeight;
left = this.originLeft + this.originWidth - width;
}
else if (!this.options.canExceedContainer && height > this.container.offsetHeight - this.originTop) {
height = this.container.offsetHeight - this.originTop;
width = this.originWidth * height / this.originHeight;
left = this.originLeft + this.originWidth - width;
}
}
break;
case ResizeAnchorCSSClass.rightAnchor:
width = this._resizeRight(event);
if (this.options.keepRatio) {
height = (width * this.originHeight) / this.originWidth;
if (height < 20) {
height = 20;
width = height * this.originWidth / this.originHeight;
}
else if (!this.options.canExceedContainer && height > this.container.offsetHeight - this.originTop) {
height = this.container.offsetHeight - this.originTop;
width = height * this.originWidth / this.originHeight;
}
}
break;
case ResizeAnchorCSSClass.bottomLeftAnchor:
height = this._resizeBottom(event);
result = this._resizeLeft(event);
left = result.left;
width = result.width;
if (this.options.keepRatio) {
if (width / this.originWidth < height / this.originHeight) {
height = (width * this.originHeight) / this.originWidth;
}
else {
width = (height * this.originWidth) / this.originHeight;
left = this.originLeft + this.originWidth - width;
}
}
break;
case ResizeAnchorCSSClass.bottomAnchor:
height = this._resizeBottom(event);
if (this.options.keepRatio) {
width = (height * this.originWidth) / this.originHeight;
if (width < 20) {
width = 20;
height = width * this.originHeight / this.originWidth;
}
else if (!this.options.canExceedContainer && width > this.container.offsetWidth - this.originLeft) {
width = this.container.offsetWidth - this.originLeft;
height = width * this.originHeight / this.originWidth;
}
}
break;
case ResizeAnchorCSSClass.bottomRightAnchor:
height = this._resizeBottom(event);
width = this._resizeRight(event);
if (this.options.keepRatio) {
if (width / this.originWidth < height / this.originHeight) {
height = (width * this.originHeight) / this.originWidth;
}
else {
width = (height * this.originWidth) / this.originHeight;
}
}
break;
}
this.resizeTarget.style.left = left + "px";
this.resizeTarget.style.top = top + "px";
this.resizeTarget.style.height = height + "px";
this.resizeTarget.style.width = width + "px";
this.emit("resize", left, top, width, height);
}
_resizeLeft(event) {
const leftResizedDistance = event.screenX - this.resizeStartLeft;
let left = this.originLeft + leftResizedDistance;
let width = this.originWidth - leftResizedDistance;
if (!this.options.canExceedContainer && left < 0) {
left = 0;
width = this.originWidth + this.originLeft;
}
else if (left > this.originLeft + this.originWidth - 20) {
left = this.originLeft + this.originWidth - 20;
width = 20; // 最小宽度
}
return {
left,
width,
};
}
_resizeTop(event) {
const topResizedDistance = event.screenY - this.resizeStartTop;
let top = this.originTop + topResizedDistance;
let height = this.originHeight - topResizedDistance;
if (!this.options.canExceedContainer && top < 0) {
top = 0;
height = this.originHeight + this.originTop;
}
else if (top > this.originTop + this.originHeight - 20) {
top = this.originTop + this.originHeight - 20;
height = 20; // 最小高度
}
return {
top,
height,
};
}
_resizeRight(event) {
if (!this.container) {
logger_1.default.error(`${this.logPrefix}_resizeRight error. No container:`, this.container);
return 0;
}
const leftResizedDistance = event.screenX - this.resizeStartLeft;
let width = this.originWidth + leftResizedDistance;
if (width < 20) {
width = 20; // 最小宽度
}
else if (!this.options.canExceedContainer && width > this.container.offsetWidth - this.originLeft) {
width = this.container.offsetWidth - this.originLeft;
}
return width;
}
_resizeBottom(event) {
if (!this.container) {
logger_1.default.error(`${this.logPrefix}_resizeBottom error. No container:`, this.container);
return 0;
}
const topResizedDistance = event.screenY - this.resizeStartTop;
let height = this.originHeight + topResizedDistance;
if (height < 20) {
height = 20; // 最小高度
}
else if (!this.options.canExceedContainer && height > this.container.offsetHeight - this.originTop) {
height = this.container.offsetHeight - this.originTop;
}
return height;
}
mouseup() {
document.removeEventListener("mousemove", this.mousemove, false);
document.removeEventListener("mouseup", this.mouseup, false);
this.currentAnchor = null;
this.resizeStartLeft = 0;
this.resizeStartTop = 0;
this.originLeft = 0;
this.originTop = 0;
this.originWidth = 0;
this.originHeight = 0;
}
on(eventName, callback) {
const callbacks = this.callbacksMap.get(eventName);
if (callbacks) {
callbacks.push(callback);
}
else {
this.callbacksMap.set(eventName, [callback]);
}
}
off(eventName, callback) {
let callbacks = this.callbacksMap.get(eventName);
if (callbacks) {
callbacks = callbacks.filter((item) => item != callback);
this.callbacksMap.set(eventName, callbacks);
}
}
emit(eventName, ...arg) {
const callbacks = this.callbacksMap.get(eventName);
if (callbacks) {
const callbacksClone = callbacks.slice();
callbacksClone.forEach((callback) => {
try {
callback.apply(null, arg); // arg must be array
}
catch (error) {
console.error("[Resizable]emit error:", callback, error);
}
});
}
}
destroy() {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
(_a = this.topLeftAnchor) === null || _a === void 0 ? void 0 : _a.removeEventListener("mousedown", this.mousedown, false);
(_b = this.topAnchor) === null || _b === void 0 ? void 0 : _b.removeEventListener("mousedown", this.mousedown, false);
(_c = this.topRightAnchor) === null || _c === void 0 ? void 0 : _c.removeEventListener("mousedown", this.mousedown, false);
(_d = this.leftAnchor) === null || _d === void 0 ? void 0 : _d.removeEventListener("mousedown", this.mousedown, false);
(_e = this.rightAnchor) === null || _e === void 0 ? void 0 : _e.removeEventListener("mousedown", this.mousedown, false);
(_f = this.bottomLeftAnchor) === null || _f === void 0 ? void 0 : _f.removeEventListener("mousedown", this.mousedown, false);
(_g = this.bottomAnchor) === null || _g === void 0 ? void 0 : _g.removeEventListener("mousedown", this.mousedown, false);
(_h = this.bottomRightAnchor) === null || _h === void 0 ? void 0 : _h.removeEventListener("mousedown", this.mousedown, false);
this.callbacksMap.clear();
if (this.options.anchorMode === ResizeAnchorMode.Both || this.options.anchorMode === ResizeAnchorMode.Edge) {
this.topAnchor && ((_j = this.resizeTarget) === null || _j === void 0 ? void 0 : _j.removeChild(this.topAnchor));
this.leftAnchor && ((_k = this.resizeTarget) === null || _k === void 0 ? void 0 : _k.removeChild(this.leftAnchor));
this.rightAnchor && ((_l = this.resizeTarget) === null || _l === void 0 ? void 0 : _l.removeChild(this.rightAnchor));
this.bottomAnchor && ((_m = this.resizeTarget) === null || _m === void 0 ? void 0 : _m.removeChild(this.bottomAnchor));
}
if (this.options.anchorMode === ResizeAnchorMode.Both || this.options.anchorMode === ResizeAnchorMode.Corner) {
this.topLeftAnchor && ((_o = this.resizeTarget) === null || _o === void 0 ? void 0 : _o.removeChild(this.topLeftAnchor));
this.topRightAnchor && ((_p = this.resizeTarget) === null || _p === void 0 ? void 0 : _p.removeChild(this.topRightAnchor));
this.bottomLeftAnchor && ((_q = this.resizeTarget) === null || _q === void 0 ? void 0 : _q.removeChild(this.bottomLeftAnchor));
this.bottomRightAnchor && ((_r = this.resizeTarget) === null || _r === void 0 ? void 0 : _r.removeChild(this.bottomRightAnchor));
}
this.topLeftAnchor = null;
this.topAnchor = null;
this.topRightAnchor = null;
this.leftAnchor = null;
this.rightAnchor = null;
this.bottomLeftAnchor = null;
this.bottomAnchor = null;
this.bottomRightAnchor = null;
this.resizeTarget = null;
this.container = null;
this.currentAnchor = null;
this.resizeStartLeft = 0;
this.resizeStartTop = 0;
this.originLeft = 0;
this.originTop = 0;
this.originWidth = 0;
this.originHeight = 0;
}
}
exports.default = Resizable;