@bplok20010/viewbox
Version:
a tool class for matrix transformation of views (rotate, scale, translate, skew, etc.)
403 lines (402 loc) • 13.9 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { Matrix2D } from "matrix2d.js";
var DEFAULT_WIDTH = 400;
var DEFAULT_HEIGHT = 400;
function isset(value) {
return !(value == null);
}
function getDefaultTransform() {
return {
a: 1,
b: 0,
c: 0,
d: 1,
x: 0,
y: 0,
scaleX: 1,
scaleY: 1,
rotation: 0,
flipX: false,
flipY: false,
skewX: 0,
skewY: 0,
};
}
/**
* ViewBox
*/
var ViewBox = /** @class */ (function () {
function ViewBox(options) {
if (options === void 0) { options = {}; }
this._matrix = new Matrix2D();
this._transform = getDefaultTransform();
this.transformOrigin = { x: 0, y: 0 };
this.options = options;
this.transformOrigin = options.transformOrigin || this.transformOrigin;
if (options.transform) {
this.setTransform(options.transform);
}
}
Object.defineProperty(ViewBox.prototype, "matrix", {
get: function () {
return this._matrix;
},
set: function (mtx) {
this._matrix = mtx;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ViewBox.prototype, "transform", {
get: function () {
this._transform.x = this.x;
this._transform.y = this.y;
return this._transform;
// return this.decompose();
},
set: function (value) {
this._transform = __assign(__assign({}, this._transform), value);
},
enumerable: false,
configurable: true
});
ViewBox.prototype.decompose = function () {
return this.matrix.decompose();
};
Object.defineProperty(ViewBox.prototype, "cx", {
get: function () {
return this.transformOrigin.x;
},
enumerable: false,
configurable: true
});
Object.defineProperty(ViewBox.prototype, "cy", {
get: function () {
return this.transformOrigin.y;
},
enumerable: false,
configurable: true
});
ViewBox.prototype.setTransformOrigin = function (x, y) {
this.transformOrigin = {
x: x,
y: y,
};
};
ViewBox.prototype.getTransformOrigin = function () {
return {
x: this.cx,
y: this.cy,
};
};
Object.defineProperty(ViewBox.prototype, "x", {
get: function () {
return this.matrix.tx;
},
set: function (value) {
var delta = value - this.x;
this.translate(delta, 0);
},
enumerable: false,
configurable: true
});
Object.defineProperty(ViewBox.prototype, "y", {
get: function () {
return this.matrix.ty;
},
set: function (value) {
var delta = value - this.y;
this.translate(0, delta);
},
enumerable: false,
configurable: true
});
ViewBox.prototype.getPosition = function () {
return {
x: this.x,
y: this.y,
};
};
ViewBox.prototype.setPosition = function (x, y) {
this.x = x;
this.y = y;
return this;
};
ViewBox.prototype.getTransform = function () {
var _a = this.matrix, a = _a.a, b = _a.b, c = _a.c, d = _a.d, tx = _a.tx, ty = _a.ty;
return __assign(__assign({}, this.transform), { a: a, b: b, c: c, d: d, x: tx, y: ty });
};
ViewBox.prototype.setTransform = function (transform) {
var _a = transform.a, a = _a === void 0 ? 1 : _a, _b = transform.b, b = _b === void 0 ? 0 : _b, _c = transform.c, c = _c === void 0 ? 0 : _c, _d = transform.d, d = _d === void 0 ? 1 : _d, _e = transform.x, x = _e === void 0 ? 0 : _e, _f = transform.y, y = _f === void 0 ? 0 : _f;
var matrix = new Matrix2D(a, b, c, d, x, y);
var decompose = matrix.decompose();
this.transform = __assign(__assign(__assign({}, getDefaultTransform()), { scaleX: decompose.scaleX, scaleY: decompose.scaleY, rotation: decompose.rotation, x: decompose.x, y: decompose.y }), transform);
this.matrix = matrix;
return this;
};
ViewBox.prototype.getMatrixObject = function () {
return this.matrix.clone();
};
ViewBox.prototype.getMatrix = function () {
var _a = this.matrix, a = _a.a, b = _a.b, c = _a.c, d = _a.d, tx = _a.tx, ty = _a.ty;
return [a, b, c, d, tx, ty];
};
/**
* 视图坐标(相对viewBox)转本地坐标(viewBox内容实际坐标)
* @examples
* viewBox.translate(100, 100)
* viewBox.globalToLocal(0, 0) // {x: -100, y: -100}
*/
ViewBox.prototype.globalToLocal = function (x, y) {
return this.getMatrixObject().invert().transformPoint(x, y);
};
/**
* 本地坐标(viewBox内容实际坐标)转视图坐标(相对viewBox)
* @examples
* viewBox.translate(100, 100)
* viewBox.localToGlobal(-100, -100) // {x: 0, y: 0}
*/
ViewBox.prototype.localToGlobal = function (x, y) {
return this.matrix.transformPoint(x, y);
};
/**
* 对viewBox内容进行平移
* @param x 相对viewBox的(视图坐标)x偏移量
* @param y 同上 y偏移量
* @returns
*/
ViewBox.prototype.translate = function (x, y) {
this.matrix.prepend(1, 0, 0, 1, x, y);
return this;
};
ViewBox.prototype.translateX = function (x) {
return this.translate(x, 0);
};
ViewBox.prototype.translateY = function (y) {
return this.translate(0, y);
};
ViewBox.prototype.scale = function (scaleX, scaleY, cx, cy) {
var m0 = new Matrix2D();
m0.scale(scaleX, scaleY, cx !== null && cx !== void 0 ? cx : this.cx, cy !== null && cy !== void 0 ? cy : this.cy);
this.matrix.prependMatrix(m0);
this.transform.scaleX *= scaleX;
this.transform.scaleY *= scaleY;
return this;
};
ViewBox.prototype.rotate = function (rotation, cx, cy) {
var m0 = new Matrix2D();
m0.rotate(rotation, cx !== null && cx !== void 0 ? cx : this.cx, cy !== null && cy !== void 0 ? cy : this.cy);
this.matrix.prependMatrix(m0);
this.transform.rotation += rotation;
return this;
};
ViewBox.prototype.flipX = function (cx, cy) {
cx = cx !== null && cx !== void 0 ? cx : this.cx;
cy = cy !== null && cy !== void 0 ? cy : this.cy;
var m0 = new Matrix2D();
m0.flipX(cx, cy);
this.matrix.prependMatrix(m0);
this.transform.flipX = !this.transform.flipX;
return this;
};
ViewBox.prototype.flipY = function (cx, cy) {
cx = cx !== null && cx !== void 0 ? cx : this.cx;
cy = cy !== null && cy !== void 0 ? cy : this.cy;
var m0 = new Matrix2D();
m0.flipY(cx, cy);
this.matrix.prependMatrix(m0);
this.transform.flipX = !this.transform.flipX;
return this;
};
ViewBox.prototype.skewX = function (value, cx, cy) {
var m0 = new Matrix2D();
m0.skewX(value, cx !== null && cx !== void 0 ? cx : this.cx, cy !== null && cy !== void 0 ? cy : this.cy);
this.matrix.prependMatrix(m0);
this.transform.skewX += value;
return this;
};
ViewBox.prototype.setSkewX = function (value, cx, cy) {
var skewX = this.transform.skewX;
var m0 = new Matrix2D();
m0.skewX(value - skewX, cx !== null && cx !== void 0 ? cx : this.cx, cy !== null && cy !== void 0 ? cy : this.cy);
this.matrix.prependMatrix(m0);
this.transform.skewX = value;
return this;
};
ViewBox.prototype.skewY = function (value, cx, cy) {
var m0 = new Matrix2D();
m0.skewY(value, cx !== null && cx !== void 0 ? cx : this.cx, cy !== null && cy !== void 0 ? cy : this.cy);
this.matrix.prependMatrix(m0);
this.transform.skewY += value;
return this;
};
ViewBox.prototype.setSkewY = function (value, cx, cy) {
var skewY = this.transform.skewY;
var m0 = new Matrix2D();
m0.skewY(value - skewY, cx !== null && cx !== void 0 ? cx : this.cx, cy !== null && cy !== void 0 ? cy : this.cy);
this.matrix.prependMatrix(m0);
this.transform.skewY = value;
return this;
};
/**
* 获取当前缩放值
* @returns
*/
ViewBox.prototype.getZoom = function () {
return this.transform.scaleX;
};
ViewBox.prototype.setZoom = function (value, cx, cy) {
var scaleX = this.transform.scaleX;
var scaleY = this.transform.scaleY;
this.transform.scaleX = value;
this.transform.scaleY = value;
cx = cx !== null && cx !== void 0 ? cx : this.cx;
cy = cy !== null && cy !== void 0 ? cy : this.cy;
var m0 = new Matrix2D();
m0.scale(value / scaleX, value / scaleY, cx, cy);
this.matrix.prependMatrix(m0);
return this;
};
ViewBox.prototype.setRotation = function (rotation, cx, cy) {
var delta = rotation - this.transform.rotation;
this.rotate(delta, cx, cy);
return this;
};
ViewBox.prototype.getObjectFitScale = function (objectFit, nodeSize, viewBoxSize) {
var scaleX = 1, scaleY = 1;
var width = nodeSize.width, height = nodeSize.height;
var vWidth = viewBoxSize.width;
var vHeight = viewBoxSize.height;
switch (objectFit) {
case "cover":
scaleX = scaleY = Math.max(vWidth / width, vHeight / height);
break;
case "none":
scaleX = scaleY = 1;
break;
case "scale-down":
scaleX = scaleY = Math.min(1, Math.min(vWidth / width, vHeight / height));
break;
case "fill":
scaleX = vWidth / width;
scaleY = vHeight / height;
break;
default:
//case "contain":
scaleX = scaleY = Math.min(vWidth / width, vHeight / height);
break;
}
return {
scaleX: scaleX,
scaleY: scaleY,
};
};
/**
* 缩放以显示指定矩形区域(基于视图的区域)内容,并将区域中心移动到指定的坐标(transformOrigin)
* @param rect
*/
ViewBox.prototype.zoomToRect = function (rect, options) {
var _a;
if (options === void 0) { options = {}; }
if (!rect) {
return this;
}
if (options.matrix) {
var m = options.matrix;
this.setTransform({
a: m[0],
b: m[1],
c: m[2],
d: m[3],
x: m[4],
y: m[5],
});
}
var objectFit = options.objectFit || "contain";
var size = (options === null || options === void 0 ? void 0 : options.viewBoxSize) ||
(options === null || options === void 0 ? void 0 : options.size) || {
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
};
var padding = (_a = options.padding) !== null && _a !== void 0 ? _a : 0;
var vWidth = size.width - padding * 2;
var vHeight = size.height - padding * 2;
var scaleX = 1, scaleY = 1;
if (isset(options.scale)) {
scaleX = scaleY = options.scale;
}
else {
var r = this.getObjectFitScale(objectFit, rect, {
width: vWidth,
height: vHeight,
});
scaleX = r.scaleX;
scaleY = r.scaleY;
}
var cx = options.transformOrigin ? options.transformOrigin.x : this.cx;
var cy = options.transformOrigin ? options.transformOrigin.y : this.cy;
var rectCx = rect.x + rect.width / 2;
var rectCy = rect.y + rect.height / 2;
this.translate(cx - rectCx, cy - rectCy);
this.scale(scaleX, scaleY, cx, cy);
return this;
};
/**
* 缩放以居中显示指定矩形区域内容
* @returns
*/
ViewBox.prototype.zoomToFit = function (rect, options) {
if (options === void 0) { options = {}; }
var size = (options === null || options === void 0 ? void 0 : options.viewBoxSize) ||
(options === null || options === void 0 ? void 0 : options.size) || {
width: DEFAULT_WIDTH,
height: DEFAULT_HEIGHT,
};
return this.zoomToRect(rect, __assign(__assign({}, options), { transformOrigin: {
x: size.width / 2,
y: size.height / 2,
} }));
};
ViewBox.prototype.reset = function () {
var m = new Matrix2D();
this.setTransform({
a: m.a,
b: m.b,
c: m.c,
d: m.d,
x: m.tx,
y: m.ty,
});
return this;
};
ViewBox.prototype.toCSS = function () {
var mtx = this.getMatrix();
return "matrix(".concat(mtx.join(","), ")");
};
/**
* alias toCSS
* @returns
*/
ViewBox.prototype.toString = function () {
return this.toCSS();
};
ViewBox.prototype.clone = function () {
var viewBox = new ViewBox({
transformOrigin: this.getTransformOrigin(),
transform: this.getTransform(),
});
return viewBox;
};
return ViewBox;
}());
export { ViewBox };