leafer-editor
Version:
**leafer-editor** 在 [leafer-ui](https://github.com/leaferjs/leafer-ui) 的基础上,集成了 图形编辑器、视图控制 、滚动条、箭头、HTML 插件,适用于在线图形编辑的场景。
1,662 lines (1,585 loc) • 613 kB
JavaScript
const Platform = {
toURL(text, fileType) {
let url = encodeURIComponent(text);
if (fileType === "text") url = "data:text/plain;charset=utf-8," + url; else if (fileType === "svg") url = "data:image/svg+xml," + url;
return url;
},
image: {
hitCanvasSize: 100,
maxCacheSize: 2560 * 1600,
maxPatternSize: 4096 * 2160,
crossOrigin: "anonymous",
getRealURL(url) {
const {prefix: prefix, suffix: suffix} = Platform.image;
if (suffix && !url.startsWith("data:") && !url.startsWith("blob:")) url += (url.includes("?") ? "&" : "?") + suffix;
if (prefix && url[0] === "/") url = prefix + url;
return url;
}
}
};
const IncrementId = {
RUNTIME: "runtime",
LEAF: "leaf",
TASK: "task",
CNAVAS: "canvas",
IMAGE: "image",
types: {},
create(typeName) {
const {types: types} = I$2;
if (types[typeName]) {
return types[typeName]++;
} else {
types[typeName] = 1;
return 0;
}
}
};
const I$2 = IncrementId;
var Answer;
(function(Answer) {
Answer[Answer["No"] = 0] = "No";
Answer[Answer["Yes"] = 1] = "Yes";
Answer[Answer["NoAndSkip"] = 2] = "NoAndSkip";
Answer[Answer["YesAndSkip"] = 3] = "YesAndSkip";
})(Answer || (Answer = {}));
const emptyData = {};
function isUndefined(value) {
return value === undefined;
}
function isNull(value) {
return value == null;
}
function isString(value) {
return typeof value === "string";
}
const {isFinite: isFinite} = Number;
function isNumber(value) {
return typeof value === "number";
}
const numberReg = /^-?\d+(?:\.\d+)?$/;
function tryToNumber(value) {
return typeof value === "string" && numberReg.test(value) ? +value : value;
}
const {isArray: isArray} = Array;
function isObject(value) {
return value && typeof value === "object";
}
function isData(value) {
return isObject(value) && !isArray(value);
}
function isEmptyData(value) {
return JSON.stringify(value) === "{}";
}
const DataHelper = {
default(t, defaultData) {
assign(defaultData, t);
assign(t, defaultData);
return t;
},
assign(t, merge, exclude) {
let value;
Object.keys(merge).forEach(key => {
var _a, _b;
value = merge[key];
if ((value === null || value === void 0 ? void 0 : value.constructor) === Object && ((_a = t[key]) === null || _a === void 0 ? void 0 : _a.constructor) === Object) return assign(t[key], merge[key], exclude && exclude[key]);
if (exclude && key in exclude) {
if (((_b = exclude[key]) === null || _b === void 0 ? void 0 : _b.constructor) === Object) assign(t[key] = {}, merge[key], exclude[key]);
return;
}
t[key] = merge[key];
});
},
copyAttrs(t, from, include) {
include.forEach(key => {
if (!isUndefined(from[key])) t[key] = from[key];
});
return t;
},
clone(data) {
return JSON.parse(JSON.stringify(data));
},
toMap(list) {
const map = {};
for (let i = 0, len = list.length; i < len; i++) map[list[i]] = true;
return map;
},
stintSet(data, attrName, value) {
value || (value = undefined);
data[attrName] !== value && (data[attrName] = value);
}
};
const {assign: assign} = DataHelper;
class LeafData {
get __useNaturalRatio() {
return true;
}
get __isLinePath() {
const {path: path} = this;
return path && path.length === 6 && path[0] === 1;
}
get __usePathBox() {
return this.__pathInputed;
}
get __blendMode() {
if (this.eraser && this.eraser !== "path") return "destination-out";
const {blendMode: blendMode} = this;
return blendMode === "pass-through" ? null : blendMode;
}
constructor(leaf) {
this.__leaf = leaf;
}
__get(name) {
if (this.__input) {
const value = this.__input[name];
if (!isUndefined(value)) return value;
}
return this[name];
}
__getData() {
const data = {
tag: this.__leaf.tag
}, {__input: __input} = this;
let inputValue;
for (let key in this) {
if (key[0] !== "_") {
inputValue = __input ? __input[key] : undefined;
data[key] = isUndefined(inputValue) ? this[key] : inputValue;
}
}
return data;
}
__setInput(name, value) {
this.__input || (this.__input = {});
this.__input[name] = value;
}
__getInput(name) {
if (this.__input) {
const value = this.__input[name];
if (!isUndefined(value)) return value;
}
if (name === "path" && !this.__pathInputed) return;
return this["_" + name];
}
__removeInput(name) {
if (this.__input && !isUndefined(this.__input[name])) this.__input[name] = undefined;
}
__getInputData(names, options) {
const data = {};
if (names) {
if (isArray(names)) {
for (let name of names) data[name] = this.__getInput(name);
} else {
for (let name in names) data[name] = this.__getInput(name);
}
} else {
let value, inputValue, {__input: __input} = this;
data.tag = this.__leaf.tag;
for (let key in this) {
if (key[0] !== "_") {
value = this["_" + key];
if (!isUndefined(value)) {
if (key === "path" && !this.__pathInputed) continue;
inputValue = __input ? __input[key] : undefined;
data[key] = isUndefined(inputValue) ? value : inputValue;
}
}
}
}
if (options) {
if (options.matrix) {
const {a: a, b: b, c: c, d: d, e: e, f: f} = this.__leaf.__localMatrix;
data.matrix = {
a: a,
b: b,
c: c,
d: d,
e: e,
f: f
};
}
}
return data;
}
__setMiddle(name, value) {
this.__middle || (this.__middle = {});
this.__middle[name] = value;
}
__getMiddle(name) {
return this.__middle && this.__middle[name];
}
__checkSingle() {
const t = this;
if (t.blendMode === "pass-through") {
const leaf = this.__leaf;
if (t.opacity < 1 && (leaf.isBranch || t.__hasMultiPaint) || leaf.__hasEraser || t.eraser || t.filter) {
t.__single = true;
} else if (t.__single) {
t.__single = false;
}
} else {
t.__single = true;
}
}
__removeNaturalSize() {
this.__naturalWidth = this.__naturalHeight = undefined;
}
destroy() {
this.__input = this.__middle = null;
}
}
let tempA, tempB, tempTo;
const {max: max$5} = Math, tempFour = [ 0, 0, 0, 0 ];
const FourNumberHelper = {
zero: [ ...tempFour ],
tempFour: tempFour,
set(to, top, right, bottom, left) {
if (right === undefined) right = bottom = left = top;
to[0] = top;
to[1] = right;
to[2] = bottom;
to[3] = left;
return to;
},
setTemp(top, right, bottom, left) {
return set$1(tempFour, top, right, bottom, left);
},
toTempAB(a, b, change) {
tempTo = change ? isNumber(a) ? b : a : [];
if (isNumber(a)) tempA = setTemp(a), tempB = b; else if (isNumber(b)) tempA = a,
tempB = setTemp(b); else tempA = a, tempB = b;
if (tempA.length !== 4) tempA = get$5(tempA);
if (tempB.length !== 4) tempB = get$5(tempB);
},
get(num, maxValue) {
let data;
if (!isNumber(num)) {
switch (num.length) {
case 4:
data = isUndefined(maxValue) ? num : [ ...num ];
break;
case 2:
data = [ num[0], num[1], num[0], num[1] ];
break;
case 3:
data = [ num[0], num[1], num[2], num[1] ];
break;
case 1:
num = num[0];
break;
default:
num = 0;
}
}
if (!data) data = [ num, num, num, num ];
if (!isUndefined(maxValue)) for (let i = 0; i < 4; i++) if (data[i] > maxValue) data[i] = maxValue;
return data;
},
max(t, other, change) {
if (isNumber(t) && isNumber(other)) return max$5(t, other);
toTempAB(t, other, change);
return set$1(tempTo, max$5(tempA[0], tempB[0]), max$5(tempA[1], tempB[1]), max$5(tempA[2], tempB[2]), max$5(tempA[3], tempB[3]));
},
add(t, other, change) {
if (isNumber(t) && isNumber(other)) return t + other;
toTempAB(t, other, change);
return set$1(tempTo, tempA[0] + tempB[0], tempA[1] + tempB[1], tempA[2] + tempB[2], tempA[3] + tempB[3]);
},
swapAndScale(t, scaleX, scaleY, change) {
if (isNumber(t)) return scaleX === scaleY ? t * scaleX : [ t * scaleY, t * scaleX ];
const to = change ? t : [];
const [top, right, bottom, left] = t.length === 4 ? t : get$5(t);
return set$1(to, bottom * scaleY, left * scaleX, top * scaleY, right * scaleX);
}
};
const {set: set$1, get: get$5, setTemp: setTemp, toTempAB: toTempAB} = FourNumberHelper;
const {round: round$3, pow: pow$1, PI: PI$3} = Math;
const MathHelper = {
within(value, min, max) {
if (isObject(min)) max = min.max, min = min.min;
if (!isUndefined(min) && value < min) value = min;
if (!isUndefined(max) && value > max) value = max;
return value;
},
fourNumber: FourNumberHelper.get,
formatRotation(rotation, unsign) {
rotation %= 360;
if (unsign) {
if (rotation < 0) rotation += 360;
} else {
if (rotation > 180) rotation -= 360;
if (rotation < -180) rotation += 360;
}
return MathHelper.float(rotation);
},
getGapRotation(addRotation, gap, oldRotation = 0) {
let rotation = addRotation + oldRotation;
if (gap > 1) {
const r = Math.abs(rotation % gap);
if (r < 1 || r > gap - 1) rotation = Math.round(rotation / gap) * gap;
}
return rotation - oldRotation;
},
float(num, maxLength) {
const a = !isUndefined(maxLength) ? pow$1(10, maxLength) : 1e12;
num = round$3(num * a) / a;
return num === -0 ? 0 : num;
},
sign(num) {
return num < 0 ? -1 : 1;
},
getScaleData(scale, size, originSize, scaleData) {
if (!scaleData) scaleData = {};
if (size) {
const scaleX = (isNumber(size) ? size : size.width || 0) / originSize.width, scaleY = (isNumber(size) ? size : size.height || 0) / originSize.height;
scaleData.scaleX = scaleX || scaleY || 1;
scaleData.scaleY = scaleY || scaleX || 1;
} else if (scale) MathHelper.assignScale(scaleData, scale);
return scaleData;
},
assignScale(scaleData, scale) {
if (isNumber(scale)) {
scaleData.scaleX = scaleData.scaleY = scale;
} else {
scaleData.scaleX = scale.x;
scaleData.scaleY = scale.y;
}
},
randInt: randInt,
randColor(opacity) {
return `rgba(${randInt(255)},${randInt(255)},${randInt(255)},${opacity || 1})`;
}
};
function randInt(num) {
return Math.round(Math.random() * num);
}
const OneRadian = PI$3 / 180;
const PI2 = PI$3 * 2;
const PI_2 = PI$3 / 2;
function getPointData() {
return {
x: 0,
y: 0
};
}
function getBoundsData() {
return {
x: 0,
y: 0,
width: 0,
height: 0
};
}
function getMatrixData() {
return {
a: 1,
b: 0,
c: 0,
d: 1,
e: 0,
f: 0
};
}
const {sin: sin$5, cos: cos$5, acos: acos, sqrt: sqrt$3} = Math;
const {float: float$2} = MathHelper;
const tempPoint$3 = {};
function getWorld() {
return Object.assign(Object.assign(Object.assign({}, getMatrixData()), getBoundsData()), {
scaleX: 1,
scaleY: 1,
rotation: 0,
skewX: 0,
skewY: 0
});
}
const MatrixHelper = {
defaultMatrix: getMatrixData(),
defaultWorld: getWorld(),
tempMatrix: {},
set(t, a = 1, b = 0, c = 0, d = 1, e = 0, f = 0) {
t.a = a;
t.b = b;
t.c = c;
t.d = d;
t.e = e;
t.f = f;
},
get: getMatrixData,
getWorld: getWorld,
copy(t, matrix) {
t.a = matrix.a;
t.b = matrix.b;
t.c = matrix.c;
t.d = matrix.d;
t.e = matrix.e;
t.f = matrix.f;
},
translate(t, x, y) {
t.e += x;
t.f += y;
},
translateInner(t, x, y, hasOrigin) {
t.e += t.a * x + t.c * y;
t.f += t.b * x + t.d * y;
if (hasOrigin) t.e -= x, t.f -= y;
},
scale(t, scaleX, scaleY = scaleX) {
t.a *= scaleX;
t.b *= scaleX;
t.c *= scaleY;
t.d *= scaleY;
},
pixelScale(t, pixelRatio, to) {
to || (to = t);
to.a = t.a * pixelRatio;
to.b = t.b * pixelRatio;
to.c = t.c * pixelRatio;
to.d = t.d * pixelRatio;
to.e = t.e * pixelRatio;
to.f = t.f * pixelRatio;
},
scaleOfOuter(t, origin, scaleX, scaleY) {
M$a.toInnerPoint(t, origin, tempPoint$3);
M$a.scaleOfInner(t, tempPoint$3, scaleX, scaleY);
},
scaleOfInner(t, origin, scaleX, scaleY = scaleX) {
M$a.translateInner(t, origin.x, origin.y);
M$a.scale(t, scaleX, scaleY);
M$a.translateInner(t, -origin.x, -origin.y);
},
rotate(t, rotation) {
const {a: a, b: b, c: c, d: d} = t;
rotation *= OneRadian;
const cosR = cos$5(rotation);
const sinR = sin$5(rotation);
t.a = a * cosR - b * sinR;
t.b = a * sinR + b * cosR;
t.c = c * cosR - d * sinR;
t.d = c * sinR + d * cosR;
},
rotateOfOuter(t, origin, rotation) {
M$a.toInnerPoint(t, origin, tempPoint$3);
M$a.rotateOfInner(t, tempPoint$3, rotation);
},
rotateOfInner(t, origin, rotation) {
M$a.translateInner(t, origin.x, origin.y);
M$a.rotate(t, rotation);
M$a.translateInner(t, -origin.x, -origin.y);
},
skew(t, skewX, skewY) {
const {a: a, b: b, c: c, d: d} = t;
if (skewY) {
skewY *= OneRadian;
t.a = a + c * skewY;
t.b = b + d * skewY;
}
if (skewX) {
skewX *= OneRadian;
t.c = c + a * skewX;
t.d = d + b * skewX;
}
},
skewOfOuter(t, origin, skewX, skewY) {
M$a.toInnerPoint(t, origin, tempPoint$3);
M$a.skewOfInner(t, tempPoint$3, skewX, skewY);
},
skewOfInner(t, origin, skewX, skewY = 0) {
M$a.translateInner(t, origin.x, origin.y);
M$a.skew(t, skewX, skewY);
M$a.translateInner(t, -origin.x, -origin.y);
},
multiply(t, child) {
const {a: a, b: b, c: c, d: d, e: e, f: f} = t;
t.a = child.a * a + child.b * c;
t.b = child.a * b + child.b * d;
t.c = child.c * a + child.d * c;
t.d = child.c * b + child.d * d;
t.e = child.e * a + child.f * c + e;
t.f = child.e * b + child.f * d + f;
},
multiplyParent(t, parent, to, abcdChanged, childScaleData) {
const {e: e, f: f} = t;
to || (to = t);
if (isUndefined(abcdChanged)) abcdChanged = t.a !== 1 || t.b || t.c || t.d !== 1;
if (abcdChanged) {
const {a: a, b: b, c: c, d: d} = t;
to.a = a * parent.a + b * parent.c;
to.b = a * parent.b + b * parent.d;
to.c = c * parent.a + d * parent.c;
to.d = c * parent.b + d * parent.d;
if (childScaleData) {
to.scaleX = parent.scaleX * childScaleData.scaleX;
to.scaleY = parent.scaleY * childScaleData.scaleY;
}
} else {
to.a = parent.a;
to.b = parent.b;
to.c = parent.c;
to.d = parent.d;
if (childScaleData) {
to.scaleX = parent.scaleX;
to.scaleY = parent.scaleY;
}
}
to.e = e * parent.a + f * parent.c + parent.e;
to.f = e * parent.b + f * parent.d + parent.f;
},
divide(t, child) {
M$a.multiply(t, M$a.tempInvert(child));
},
divideParent(t, parent) {
M$a.multiplyParent(t, M$a.tempInvert(parent));
},
tempInvert(t) {
const {tempMatrix: tempMatrix} = M$a;
M$a.copy(tempMatrix, t);
M$a.invert(tempMatrix);
return tempMatrix;
},
invert(t) {
const {a: a, b: b, c: c, d: d, e: e, f: f} = t;
if (!b && !c) {
if (a === 1 && d === 1) {
t.e = -e;
t.f = -f;
} else {
const s = 1 / (a * d);
t.a = d * s;
t.d = a * s;
t.e = -e * d * s;
t.f = -f * a * s;
}
} else {
const s = 1 / (a * d - b * c);
t.a = d * s;
t.b = -b * s;
t.c = -c * s;
t.d = a * s;
t.e = -(e * d - f * c) * s;
t.f = -(f * a - e * b) * s;
}
},
toOuterPoint(t, inner, to, distance) {
const {x: x, y: y} = inner;
to || (to = inner);
to.x = x * t.a + y * t.c;
to.y = x * t.b + y * t.d;
if (!distance) {
to.x += t.e;
to.y += t.f;
}
},
toInnerPoint(t, outer, to, distance) {
const {a: a, b: b, c: c, d: d} = t;
const s = 1 / (a * d - b * c);
const {x: x, y: y} = outer;
to || (to = outer);
to.x = (x * d - y * c) * s;
to.y = (y * a - x * b) * s;
if (!distance) {
const {e: e, f: f} = t;
to.x -= (e * d - f * c) * s;
to.y -= (f * a - e * b) * s;
}
},
setLayout(t, layout, origin, around, bcChanged) {
const {x: x, y: y, scaleX: scaleX, scaleY: scaleY} = layout;
if (isUndefined(bcChanged)) bcChanged = layout.rotation || layout.skewX || layout.skewY;
if (bcChanged) {
const {rotation: rotation, skewX: skewX, skewY: skewY} = layout;
const r = rotation * OneRadian;
const cosR = cos$5(r);
const sinR = sin$5(r);
if (skewX || skewY) {
const sx = skewX * OneRadian;
const sy = skewY * OneRadian;
t.a = (cosR + sy * -sinR) * scaleX;
t.b = (sinR + sy * cosR) * scaleX;
t.c = (-sinR + sx * cosR) * scaleY;
t.d = (cosR + sx * sinR) * scaleY;
} else {
t.a = cosR * scaleX;
t.b = sinR * scaleX;
t.c = -sinR * scaleY;
t.d = cosR * scaleY;
}
} else {
t.a = scaleX;
t.b = 0;
t.c = 0;
t.d = scaleY;
}
t.e = x;
t.f = y;
if (origin = origin || around) M$a.translateInner(t, -origin.x, -origin.y, !around);
},
getLayout(t, origin, around, firstSkewY) {
const {a: a, b: b, c: c, d: d, e: e, f: f} = t;
let x = e, y = f, scaleX, scaleY, rotation, skewX, skewY;
if (b || c) {
const s = a * d - b * c;
if (c && !firstSkewY) {
scaleX = sqrt$3(a * a + b * b);
scaleY = s / scaleX;
const cosR = a / scaleX;
rotation = b > 0 ? acos(cosR) : -acos(cosR);
} else {
scaleY = sqrt$3(c * c + d * d);
scaleX = s / scaleY;
const cosR = c / scaleY;
rotation = PI_2 - (d > 0 ? acos(-cosR) : -acos(cosR));
}
const cosR = float$2(cos$5(rotation));
const sinR = sin$5(rotation);
scaleX = float$2(scaleX), scaleY = float$2(scaleY);
skewX = cosR ? float$2((c / scaleY + sinR) / cosR / OneRadian, 9) : 0;
skewY = cosR ? float$2((b / scaleX - sinR) / cosR / OneRadian, 9) : 0;
rotation = float$2(rotation / OneRadian);
} else {
scaleX = a;
scaleY = d;
rotation = skewX = skewY = 0;
}
if (origin = around || origin) {
x += origin.x * a + origin.y * c;
y += origin.x * b + origin.y * d;
if (!around) x -= origin.x, y -= origin.y;
}
return {
x: x,
y: y,
scaleX: scaleX,
scaleY: scaleY,
rotation: rotation,
skewX: skewX,
skewY: skewY
};
},
withScale(t, scaleX, scaleY = scaleX) {
const world = t;
if (!scaleX || !scaleY) {
const {a: a, b: b, c: c, d: d} = t;
if (b || c) {
scaleX = sqrt$3(a * a + b * b);
scaleY = (a * d - b * c) / scaleX;
} else {
scaleX = a;
scaleY = d;
}
}
world.scaleX = scaleX;
world.scaleY = scaleY;
return world;
},
reset(t) {
M$a.set(t);
}
};
const M$a = MatrixHelper;
const {toInnerPoint: toInnerPoint$2, toOuterPoint: toOuterPoint$3} = MatrixHelper;
const {sin: sin$4, cos: cos$4, abs: abs$6, sqrt: sqrt$2, atan2: atan2$2, min: min$1, round: round$2} = Math;
const PointHelper = {
defaultPoint: getPointData(),
tempPoint: {},
tempRadiusPoint: {},
set(t, x = 0, y = 0) {
t.x = x;
t.y = y;
},
setRadius(t, x, y) {
t.radiusX = x;
t.radiusY = isUndefined(y) ? x : y;
},
copy(t, point) {
t.x = point.x;
t.y = point.y;
},
copyFrom(t, x, y) {
t.x = x;
t.y = y;
},
round(t, halfPixel) {
t.x = halfPixel ? round$2(t.x - .5) + .5 : round$2(t.x);
t.y = halfPixel ? round$2(t.y - .5) + .5 : round$2(t.y);
},
move(t, x, y) {
if (isObject(x)) t.x += x.x, t.y += x.y; else t.x += x, t.y += y;
},
scale(t, scaleX, scaleY = scaleX) {
if (t.x) t.x *= scaleX;
if (t.y) t.y *= scaleY;
},
scaleOf(t, origin, scaleX, scaleY = scaleX) {
t.x += (t.x - origin.x) * (scaleX - 1);
t.y += (t.y - origin.y) * (scaleY - 1);
},
rotate(t, rotation, origin) {
if (!origin) origin = P$7.defaultPoint;
rotation *= OneRadian;
const cosR = cos$4(rotation);
const sinR = sin$4(rotation);
const rx = t.x - origin.x;
const ry = t.y - origin.y;
t.x = origin.x + rx * cosR - ry * sinR;
t.y = origin.y + rx * sinR + ry * cosR;
},
tempToInnerOf(t, matrix) {
const {tempPoint: temp} = P$7;
copy$d(temp, t);
toInnerPoint$2(matrix, temp, temp);
return temp;
},
tempToOuterOf(t, matrix) {
const {tempPoint: temp} = P$7;
copy$d(temp, t);
toOuterPoint$3(matrix, temp, temp);
return temp;
},
tempToInnerRadiusPointOf(t, matrix) {
const {tempRadiusPoint: temp} = P$7;
copy$d(temp, t);
P$7.toInnerRadiusPointOf(t, matrix, temp);
return temp;
},
toInnerRadiusPointOf(t, matrix, to) {
to || (to = t);
toInnerPoint$2(matrix, t, to);
to.radiusX = Math.abs(t.radiusX / matrix.scaleX);
to.radiusY = Math.abs(t.radiusY / matrix.scaleY);
},
toInnerOf(t, matrix, to) {
toInnerPoint$2(matrix, t, to);
},
toOuterOf(t, matrix, to) {
toOuterPoint$3(matrix, t, to);
},
getCenter(t, to) {
return {
x: t.x + (to.x - t.x) / 2,
y: t.y + (to.y - t.y) / 2
};
},
getCenterX(x1, x2) {
return x1 + (x2 - x1) / 2;
},
getCenterY(y1, y2) {
return y1 + (y2 - y1) / 2;
},
getDistance(t, point) {
return getDistanceFrom(t.x, t.y, point.x, point.y);
},
getDistanceFrom(x1, y1, x2, y2) {
const x = abs$6(x2 - x1);
const y = abs$6(y2 - y1);
return sqrt$2(x * x + y * y);
},
getMinDistanceFrom(x1, y1, x2, y2, x3, y3) {
return min$1(getDistanceFrom(x1, y1, x2, y2), getDistanceFrom(x2, y2, x3, y3));
},
getAngle(t, to) {
return getAtan2(t, to) / OneRadian;
},
getRotation(t, origin, to, toOrigin) {
if (!toOrigin) toOrigin = origin;
return P$7.getRadianFrom(t.x, t.y, origin.x, origin.y, to.x, to.y, toOrigin.x, toOrigin.y) / OneRadian;
},
getRadianFrom(fromX, fromY, originX, originY, toX, toY, toOriginX, toOriginY) {
if (isUndefined(toOriginX)) toOriginX = originX, toOriginY = originY;
const a = fromX - originX;
const b = fromY - originY;
const c = toX - toOriginX;
const d = toY - toOriginY;
return Math.atan2(a * d - b * c, a * c + b * d);
},
getAtan2(t, to) {
return atan2$2(to.y - t.y, to.x - t.x);
},
getDistancePoint(t, to, distance, changeTo) {
const r = getAtan2(t, to);
to = changeTo ? to : {};
to.x = t.x + cos$4(r) * distance;
to.y = t.y + sin$4(r) * distance;
return to;
},
toNumberPoints(originPoints) {
let points = originPoints;
if (isObject(originPoints[0])) points = [], originPoints.forEach(p => points.push(p.x, p.y));
return points;
},
reset(t) {
P$7.reset(t);
}
};
const P$7 = PointHelper;
const {getDistanceFrom: getDistanceFrom, copy: copy$d, getAtan2: getAtan2} = P$7;
class Point {
constructor(x, y) {
this.set(x, y);
}
set(x, y) {
isObject(x) ? PointHelper.copy(this, x) : PointHelper.set(this, x, y);
return this;
}
get() {
const {x: x, y: y} = this;
return {
x: x,
y: y
};
}
clone() {
return new Point(this);
}
move(x, y) {
PointHelper.move(this, x, y);
return this;
}
scale(scaleX, scaleY) {
PointHelper.scale(this, scaleX, scaleY);
return this;
}
scaleOf(origin, scaleX, scaleY) {
PointHelper.scaleOf(this, origin, scaleX, scaleY);
return this;
}
rotate(rotation, origin) {
PointHelper.rotate(this, rotation, origin);
return this;
}
rotateOf(origin, rotation) {
PointHelper.rotate(this, rotation, origin);
return this;
}
getRotation(origin, to, toOrigin) {
return PointHelper.getRotation(this, origin, to, toOrigin);
}
toInnerOf(matrix, to) {
PointHelper.toInnerOf(this, matrix, to);
return this;
}
toOuterOf(matrix, to) {
PointHelper.toOuterOf(this, matrix, to);
return this;
}
getCenter(to) {
return new Point(PointHelper.getCenter(this, to));
}
getDistance(to) {
return PointHelper.getDistance(this, to);
}
getDistancePoint(to, distance, changeTo) {
return new Point(PointHelper.getDistancePoint(this, to, distance, changeTo));
}
getAngle(to) {
return PointHelper.getAngle(this, to);
}
getAtan2(to) {
return PointHelper.getAtan2(this, to);
}
reset() {
PointHelper.reset(this);
return this;
}
}
const tempPoint$2 = new Point;
class Matrix {
constructor(a, b, c, d, e, f) {
this.set(a, b, c, d, e, f);
}
set(a, b, c, d, e, f) {
isObject(a) ? MatrixHelper.copy(this, a) : MatrixHelper.set(this, a, b, c, d, e, f);
return this;
}
setWith(dataWithScale) {
MatrixHelper.copy(this, dataWithScale);
this.scaleX = dataWithScale.scaleX;
this.scaleY = dataWithScale.scaleY;
return this;
}
get() {
const {a: a, b: b, c: c, d: d, e: e, f: f} = this;
return {
a: a,
b: b,
c: c,
d: d,
e: e,
f: f
};
}
clone() {
return new Matrix(this);
}
translate(x, y) {
MatrixHelper.translate(this, x, y);
return this;
}
translateInner(x, y) {
MatrixHelper.translateInner(this, x, y);
return this;
}
scale(x, y) {
MatrixHelper.scale(this, x, y);
return this;
}
scaleWith(x, y) {
MatrixHelper.scale(this, x, y);
this.scaleX *= x;
this.scaleY *= y || x;
return this;
}
pixelScale(pixelRatio) {
MatrixHelper.pixelScale(this, pixelRatio);
return this;
}
scaleOfOuter(origin, x, y) {
MatrixHelper.scaleOfOuter(this, origin, x, y);
return this;
}
scaleOfInner(origin, x, y) {
MatrixHelper.scaleOfInner(this, origin, x, y);
return this;
}
rotate(angle) {
MatrixHelper.rotate(this, angle);
return this;
}
rotateOfOuter(origin, angle) {
MatrixHelper.rotateOfOuter(this, origin, angle);
return this;
}
rotateOfInner(origin, angle) {
MatrixHelper.rotateOfInner(this, origin, angle);
return this;
}
skew(x, y) {
MatrixHelper.skew(this, x, y);
return this;
}
skewOfOuter(origin, x, y) {
MatrixHelper.skewOfOuter(this, origin, x, y);
return this;
}
skewOfInner(origin, x, y) {
MatrixHelper.skewOfInner(this, origin, x, y);
return this;
}
multiply(child) {
MatrixHelper.multiply(this, child);
return this;
}
multiplyParent(parent) {
MatrixHelper.multiplyParent(this, parent);
return this;
}
divide(child) {
MatrixHelper.divide(this, child);
return this;
}
divideParent(parent) {
MatrixHelper.divideParent(this, parent);
return this;
}
invert() {
MatrixHelper.invert(this);
return this;
}
invertWith() {
MatrixHelper.invert(this);
this.scaleX = 1 / this.scaleX;
this.scaleY = 1 / this.scaleY;
return this;
}
toOuterPoint(inner, to, distance) {
MatrixHelper.toOuterPoint(this, inner, to, distance);
}
toInnerPoint(outer, to, distance) {
MatrixHelper.toInnerPoint(this, outer, to, distance);
}
setLayout(data, origin, around) {
MatrixHelper.setLayout(this, data, origin, around);
return this;
}
getLayout(origin, around, firstSkewY) {
return MatrixHelper.getLayout(this, origin, around, firstSkewY);
}
withScale(scaleX, scaleY) {
return MatrixHelper.withScale(this, scaleX, scaleY);
}
reset() {
MatrixHelper.reset(this);
}
}
const tempMatrix$2 = new Matrix;
const TwoPointBoundsHelper = {
tempPointBounds: {},
setPoint(t, minX, minY) {
t.minX = t.maxX = minX;
t.minY = t.maxY = minY;
},
addPoint(t, x, y) {
t.minX = x < t.minX ? x : t.minX;
t.minY = y < t.minY ? y : t.minY;
t.maxX = x > t.maxX ? x : t.maxX;
t.maxY = y > t.maxY ? y : t.maxY;
},
addBounds(t, x, y, width, height) {
addPoint$4(t, x, y);
addPoint$4(t, x + width, y + height);
},
copy(t, pb) {
t.minX = pb.minX;
t.minY = pb.minY;
t.maxX = pb.maxX;
t.maxY = pb.maxY;
},
addPointBounds(t, pb) {
t.minX = pb.minX < t.minX ? pb.minX : t.minX;
t.minY = pb.minY < t.minY ? pb.minY : t.minY;
t.maxX = pb.maxX > t.maxX ? pb.maxX : t.maxX;
t.maxY = pb.maxY > t.maxY ? pb.maxY : t.maxY;
},
toBounds(t, setBounds) {
setBounds.x = t.minX;
setBounds.y = t.minY;
setBounds.width = t.maxX - t.minX;
setBounds.height = t.maxY - t.minY;
}
};
const {addPoint: addPoint$4} = TwoPointBoundsHelper;
var Direction4;
(function(Direction4) {
Direction4[Direction4["top"] = 0] = "top";
Direction4[Direction4["right"] = 1] = "right";
Direction4[Direction4["bottom"] = 2] = "bottom";
Direction4[Direction4["left"] = 3] = "left";
})(Direction4 || (Direction4 = {}));
var Direction9;
(function(Direction9) {
Direction9[Direction9["topLeft"] = 0] = "topLeft";
Direction9[Direction9["top"] = 1] = "top";
Direction9[Direction9["topRight"] = 2] = "topRight";
Direction9[Direction9["right"] = 3] = "right";
Direction9[Direction9["bottomRight"] = 4] = "bottomRight";
Direction9[Direction9["bottom"] = 5] = "bottom";
Direction9[Direction9["bottomLeft"] = 6] = "bottomLeft";
Direction9[Direction9["left"] = 7] = "left";
Direction9[Direction9["center"] = 8] = "center";
Direction9[Direction9["top-left"] = 0] = "top-left";
Direction9[Direction9["top-right"] = 2] = "top-right";
Direction9[Direction9["bottom-right"] = 4] = "bottom-right";
Direction9[Direction9["bottom-left"] = 6] = "bottom-left";
})(Direction9 || (Direction9 = {}));
const directionData = [ {
x: 0,
y: 0
}, {
x: .5,
y: 0
}, {
x: 1,
y: 0
}, {
x: 1,
y: .5
}, {
x: 1,
y: 1
}, {
x: .5,
y: 1
}, {
x: 0,
y: 1
}, {
x: 0,
y: .5
}, {
x: .5,
y: .5
} ];
directionData.forEach(item => item.type = "percent");
const AroundHelper = {
directionData: directionData,
tempPoint: {},
get: get$4,
toPoint(around, box, to, onlyBoxSize, content, onlyContentSize) {
const point = get$4(around);
to.x = point.x;
to.y = point.y;
if (point.type === "percent") {
to.x *= box.width;
to.y *= box.height;
if (content) {
if (!onlyContentSize) to.x -= content.x, to.y -= content.y;
if (point.x) to.x -= point.x === 1 ? content.width : point.x === .5 ? point.x * content.width : 0;
if (point.y) to.y -= point.y === 1 ? content.height : point.y === .5 ? point.y * content.height : 0;
}
}
if (!onlyBoxSize) to.x += box.x, to.y += box.y;
},
getPoint(around, box, to) {
if (!to) to = {};
AroundHelper.toPoint(around, box, to, true);
return to;
}
};
function get$4(around) {
return isString(around) ? directionData[Direction9[around]] : around;
}
const {toPoint: toPoint$6} = AroundHelper;
const AlignHelper = {
toPoint(align, content, box, to, onlyBoxSize, onlyContentSize) {
toPoint$6(align, box, to, onlyBoxSize, content, onlyContentSize);
}
};
const {tempPointBounds: tempPointBounds$1, setPoint: setPoint$5, addPoint: addPoint$3, toBounds: toBounds$3} = TwoPointBoundsHelper;
const {toOuterPoint: toOuterPoint$2} = MatrixHelper;
const {float: float$1, fourNumber: fourNumber} = MathHelper;
const {floor: floor$2, ceil: ceil$2} = Math;
let right$4, bottom$3, boundsRight, boundsBottom;
const point$1 = {};
const toPoint$5 = {};
const tempBounds$3 = {};
const BoundsHelper = {
tempBounds: tempBounds$3,
set(t, x = 0, y = 0, width = 0, height = 0) {
t.x = x;
t.y = y;
t.width = width;
t.height = height;
},
copy(t, bounds) {
t.x = bounds.x;
t.y = bounds.y;
t.width = bounds.width;
t.height = bounds.height;
},
copyAndSpread(t, bounds, spread, isShrink, side) {
const {x: x, y: y, width: width, height: height} = bounds;
if (isArray(spread)) {
const four = fourNumber(spread);
isShrink ? B.set(t, x + four[3], y + four[0], width - four[1] - four[3], height - four[2] - four[0]) : B.set(t, x - four[3], y - four[0], width + four[1] + four[3], height + four[2] + four[0]);
} else {
if (isShrink) spread = -spread;
B.set(t, x - spread, y - spread, width + spread * 2, height + spread * 2);
}
if (side) {
if (side === "width") t.y = y, t.height = height; else t.x = x, t.width = width;
}
},
minX(t) {
return t.width > 0 ? t.x : t.x + t.width;
},
minY(t) {
return t.height > 0 ? t.y : t.y + t.height;
},
maxX(t) {
return t.width > 0 ? t.x + t.width : t.x;
},
maxY(t) {
return t.height > 0 ? t.y + t.height : t.y;
},
move(t, x, y) {
t.x += x;
t.y += y;
},
scroll(t, data) {
t.x += data.scrollX;
t.y += data.scrollY;
},
getByMove(t, x, y) {
t = Object.assign({}, t);
B.move(t, x, y);
return t;
},
toOffsetOutBounds(t, to, offsetBounds) {
if (!to) to = t; else copy$c(to, t);
if (!offsetBounds) offsetBounds = t;
to.offsetX = B.maxX(offsetBounds);
to.offsetY = B.maxY(offsetBounds);
B.move(to, -to.offsetX, -to.offsetY);
},
scale(t, scaleX, scaleY = scaleX, onlySize) {
onlySize || PointHelper.scale(t, scaleX, scaleY);
t.width *= scaleX;
t.height *= scaleY;
},
scaleOf(t, origin, scaleX, scaleY = scaleX) {
PointHelper.scaleOf(t, origin, scaleX, scaleY);
t.width *= scaleX;
t.height *= scaleY;
},
tempToOuterOf(t, matrix) {
B.copy(tempBounds$3, t);
B.toOuterOf(tempBounds$3, matrix);
return tempBounds$3;
},
getOuterOf(t, matrix) {
t = Object.assign({}, t);
B.toOuterOf(t, matrix);
return t;
},
toOuterOf(t, matrix, to) {
to || (to = t);
if (matrix.b === 0 && matrix.c === 0) {
const {a: a, d: d} = matrix;
if (a > 0) {
to.width = t.width * a;
to.x = matrix.e + t.x * a;
} else {
to.width = t.width * -a;
to.x = matrix.e + t.x * a - to.width;
}
if (d > 0) {
to.height = t.height * d;
to.y = matrix.f + t.y * d;
} else {
to.height = t.height * -d;
to.y = matrix.f + t.y * d - to.height;
}
} else {
point$1.x = t.x;
point$1.y = t.y;
toOuterPoint$2(matrix, point$1, toPoint$5);
setPoint$5(tempPointBounds$1, toPoint$5.x, toPoint$5.y);
point$1.x = t.x + t.width;
toOuterPoint$2(matrix, point$1, toPoint$5);
addPoint$3(tempPointBounds$1, toPoint$5.x, toPoint$5.y);
point$1.y = t.y + t.height;
toOuterPoint$2(matrix, point$1, toPoint$5);
addPoint$3(tempPointBounds$1, toPoint$5.x, toPoint$5.y);
point$1.x = t.x;
toOuterPoint$2(matrix, point$1, toPoint$5);
addPoint$3(tempPointBounds$1, toPoint$5.x, toPoint$5.y);
toBounds$3(tempPointBounds$1, to);
}
},
toInnerOf(t, matrix, to) {
to || (to = t);
B.move(to, -matrix.e, -matrix.f);
B.scale(to, 1 / matrix.a, 1 / matrix.d);
},
getFitMatrix(t, put, baseScale = 1) {
const scale = Math.min(baseScale, B.getFitScale(t, put));
return new Matrix(scale, 0, 0, scale, -put.x * scale, -put.y * scale);
},
getFitScale(t, put, isCoverMode) {
const sw = t.width / put.width, sh = t.height / put.height;
return isCoverMode ? Math.max(sw, sh) : Math.min(sw, sh);
},
put(t, put, align = "center", putScale = 1, changeSize = true, to) {
to || (to = put);
if (isString(putScale)) putScale = B.getFitScale(t, put, putScale === "cover");
tempBounds$3.width = changeSize ? put.width *= putScale : put.width * putScale;
tempBounds$3.height = changeSize ? put.height *= putScale : put.height * putScale;
AlignHelper.toPoint(align, tempBounds$3, t, to, true, true);
},
getSpread(t, spread, side) {
const n = {};
B.copyAndSpread(n, t, spread, false, side);
return n;
},
spread(t, spread, side) {
B.copyAndSpread(t, t, spread, false, side);
},
shrink(t, shrink, side) {
B.copyAndSpread(t, t, shrink, true, side);
},
ceil(t) {
const {x: x, y: y} = t;
t.x = floor$2(t.x);
t.y = floor$2(t.y);
t.width = x > t.x ? ceil$2(t.width + x - t.x) : ceil$2(t.width);
t.height = y > t.y ? ceil$2(t.height + y - t.y) : ceil$2(t.height);
},
unsign(t) {
if (t.width < 0) {
t.x += t.width;
t.width = -t.width;
}
if (t.height < 0) {
t.y += t.height;
t.height = -t.height;
}
},
float(t, maxLength) {
t.x = float$1(t.x, maxLength);
t.y = float$1(t.y, maxLength);
t.width = float$1(t.width, maxLength);
t.height = float$1(t.height, maxLength);
},
add(t, bounds, isPoint) {
right$4 = t.x + t.width;
bottom$3 = t.y + t.height;
boundsRight = bounds.x;
boundsBottom = bounds.y;
if (!isPoint) {
boundsRight += bounds.width;
boundsBottom += bounds.height;
}
right$4 = right$4 > boundsRight ? right$4 : boundsRight;
bottom$3 = bottom$3 > boundsBottom ? bottom$3 : boundsBottom;
t.x = t.x < bounds.x ? t.x : bounds.x;
t.y = t.y < bounds.y ? t.y : bounds.y;
t.width = right$4 - t.x;
t.height = bottom$3 - t.y;
},
addList(t, list) {
B.setListWithFn(t, list, undefined, true);
},
setList(t, list, addMode = false) {
B.setListWithFn(t, list, undefined, addMode);
},
addListWithFn(t, list, boundsDataFn) {
B.setListWithFn(t, list, boundsDataFn, true);
},
setListWithFn(t, list, boundsDataFn, addMode = false) {
let bounds, first = true;
for (let i = 0, len = list.length; i < len; i++) {
bounds = boundsDataFn ? boundsDataFn(list[i], i) : list[i];
if (bounds && (bounds.width || bounds.height)) {
if (first) {
first = false;
if (!addMode) copy$c(t, bounds);
} else {
add$2(t, bounds);
}
}
}
if (first) B.reset(t);
},
setPoints(t, points) {
points.forEach((point, index) => index === 0 ? setPoint$5(tempPointBounds$1, point.x, point.y) : addPoint$3(tempPointBounds$1, point.x, point.y));
toBounds$3(tempPointBounds$1, t);
},
setPoint(t, point) {
B.set(t, point.x, point.y);
},
addPoint(t, point) {
add$2(t, point, true);
},
getPoints(t) {
const {x: x, y: y, width: width, height: height} = t;
return [ {
x: x,
y: y
}, {
x: x + width,
y: y
}, {
x: x + width,
y: y + height
}, {
x: x,
y: y + height
} ];
},
hitRadiusPoint(t, point, pointMatrix) {
if (pointMatrix) point = PointHelper.tempToInnerRadiusPointOf(point, pointMatrix);
return point.x >= t.x - point.radiusX && point.x <= t.x + t.width + point.radiusX && (point.y >= t.y - point.radiusY && point.y <= t.y + t.height + point.radiusY);
},
hitPoint(t, point, pointMatrix) {
if (pointMatrix) point = PointHelper.tempToInnerOf(point, pointMatrix);
return point.x >= t.x && point.x <= t.x + t.width && (point.y >= t.y && point.y <= t.y + t.height);
},
hit(t, other, otherMatrix) {
if (otherMatrix) other = B.tempToOuterOf(other, otherMatrix);
return !(t.y + t.height < other.y || other.y + other.height < t.y || t.x + t.width < other.x || other.x + other.width < t.x);
},
includes(t, other, otherMatrix) {
if (otherMatrix) other = B.tempToOuterOf(other, otherMatrix);
return t.x <= other.x && t.y <= other.y && t.x + t.width >= other.x + other.width && t.y + t.height >= other.y + other.height;
},
getIntersectData(t, other, otherMatrix) {
if (otherMatrix) other = B.tempToOuterOf(other, otherMatrix);
if (!B.hit(t, other)) return getBoundsData();
let {x: x, y: y, width: width, height: height} = other;
right$4 = x + width;
bottom$3 = y + height;
boundsRight = t.x + t.width;
boundsBottom = t.y + t.height;
x = x > t.x ? x : t.x;
y = y > t.y ? y : t.y;
right$4 = right$4 < boundsRight ? right$4 : boundsRight;
bottom$3 = bottom$3 < boundsBottom ? bottom$3 : boundsBottom;
width = right$4 - x;
height = bottom$3 - y;
return {
x: x,
y: y,
width: width,
height: height
};
},
intersect(t, other, otherMatrix) {
B.copy(t, B.getIntersectData(t, other, otherMatrix));
},
isSame(t, bounds) {
return t.x === bounds.x && t.y === bounds.y && t.width === bounds.width && t.height === bounds.height;
},
isEmpty(t) {
return t.x === 0 && t.y === 0 && t.width === 0 && t.height === 0;
},
reset(t) {
B.set(t);
}
};
const B = BoundsHelper;
const {add: add$2, copy: copy$c} = B;
class Bounds {
get minX() {
return BoundsHelper.minX(this);
}
get minY() {
return BoundsHelper.minY(this);
}
get maxX() {
return BoundsHelper.maxX(this);
}
get maxY() {
return BoundsHelper.maxY(this);
}
constructor(x, y, width, height) {
this.set(x, y, width, height);
}
set(x, y, width, height) {
isObject(x) ? BoundsHelper.copy(this, x) : BoundsHelper.set(this, x, y, width, height);
return this;
}
get() {
const {x: x, y: y, width: width, height: height} = this;
return {
x: x,
y: y,
width: width,
height: height
};
}
clone() {
return new Bounds(this);
}
move(x, y) {
BoundsHelper.move(this, x, y);
return this;
}
scale(scaleX, scaleY, onlySize) {
BoundsHelper.scale(this, scaleX, scaleY, onlySize);
return this;
}
scaleOf(origin, scaleX, scaleY) {
BoundsHelper.scaleOf(this, origin, scaleX, scaleY);
return this;
}
toOuterOf(matrix, to) {
BoundsHelper.toOuterOf(this, matrix, to);
return this;
}
toInnerOf(matrix, to) {
BoundsHelper.toInnerOf(this, matrix, to);
return this;
}
getFitMatrix(put, baseScale) {
return BoundsHelper.getFitMatrix(this, put, baseScale);
}
put(put, align, putScale) {
BoundsHelper.put(this, put, align, putScale);
}
spread(fourNumber, side) {
BoundsHelper.spread(this, fourNumber, side);
return this;
}
shrink(fourNumber, side) {
BoundsHelper.shrink(this, fourNumber, side);
return this;
}
ceil() {
BoundsHelper.ceil(this);
return this;
}
unsign() {
BoundsHelper.unsign(this);
return this;
}
float(maxLength) {
BoundsHelper.float(this, maxLength);
return this;
}
add(bounds) {
BoundsHelper.add(this, bounds);
return this;
}
addList(boundsList) {
BoundsHelper.setList(this, boundsList, true);
return this;
}
setList(boundsList) {
BoundsHelper.setList(this, boundsList);
return this;
}
addListWithFn(list, boundsDataFn) {
BoundsHelper.setListWithFn(this, list, boundsDataFn, true);
return this;
}
setListWithFn(list, boundsDataFn) {
BoundsHelper.setListWithFn(this, list, boundsDataFn);
return this;
}
setPoint(point) {
BoundsHelper.setPoint(this, point);
return this;
}
setPoints(points) {
BoundsHelper.setPoints(this, points);
return this;
}
addPoint(point) {
BoundsHelper.addPoint(this, point);
return this;
}
getPoints() {
return BoundsHelper.getPoints(this);
}
hitPoint(point, pointMatrix) {
return BoundsHelper.hitPoint(this, point, pointMatrix);
}
hitRadiusPoint(point, pointMatrix) {
return BoundsHelper.hitRadiusPoint(this, point, pointMatrix);
}
hit(bounds, boundsMatrix) {
return BoundsHelper.hit(this, bounds, boundsMatrix);
}
includes(bounds, boundsMatrix) {
return BoundsHelper.includes(this, bounds, boundsMatrix);
}
intersect(bounds, boundsMatrix) {
BoundsHelper.intersect(this, bounds, boundsMatrix);
return this;
}
getIntersect(bounds, boundsMatrix) {
return new Bounds(BoundsHelper.getIntersectData(this, bounds, boundsMatrix));
}
isSame(bounds) {
return BoundsHelper.isSame(this, bounds);
}
isEmpty() {
return BoundsHelper.isEmpty(this);
}
reset() {
BoundsHelper.reset(this);
}
}
const tempBounds$2 = new Bounds;
class AutoBounds {
constructor(top, right, bottom, left, width, height) {
isObject(top) ? this.copy(top) : this.set(top, right, bottom, left, width, height);
}
set(top = 0, right = 0, bottom = 0, left = 0, width = 0, height = 0) {
this.top = top;
this.right = right;
this.bottom = bottom;
this.left = left;
this.width = width;
this.height = height;
}
copy(autoSize) {
const {top: top, right: right, bottom: bottom, left: left, width: width, hei