@leafer-in/resize
Version:
258 lines (221 loc) • 9.02 kB
JavaScript
import { PathCommandMap, MatrixHelper, Direction9, isUndefined, isArray, isObject, Leaf, Text, Path, Line, Polygon, Group, Box, Plugin } from "@leafer-ui/draw";
const {M: M, L: L, C: C, Q: Q, Z: Z, N: N, D: D, X: X, G: G, F: F, O: O, P: P, U: U} = PathCommandMap;
const PathScaler = {
scale(data, scaleX, scaleY) {
if (!data) return;
let command;
let i = 0, len = data.length;
while (i < len) {
command = data[i];
switch (command) {
case M:
case L:
scalePoints(data, scaleX, scaleY, i, 1);
i += 3;
break;
case C:
scalePoints(data, scaleX, scaleY, i, 3);
i += 7;
break;
case Q:
scalePoints(data, scaleX, scaleY, i, 2);
i += 5;
break;
case Z:
i += 1;
break;
case N:
scalePoints(data, scaleX, scaleY, i, 2);
i += 5;
break;
case D:
scalePoints(data, scaleX, scaleY, i, 2);
i += 9;
break;
case X:
scalePoints(data, scaleX, scaleY, i, 2);
i += 6;
break;
case G:
scalePoints(data, scaleX, scaleY, i, 2);
i += 9;
break;
case F:
scalePoints(data, scaleX, scaleY, i, 2);
i += 5;
break;
case O:
data[i] = G;
data.splice(i + 4, 0, data[i + 3], 0);
scalePoints(data, scaleX, scaleY, i, 2);
i += 7 + 2;
len += 2;
break;
case P:
data[i] = F;
data.splice(i + 4, 0, data[i + 3]);
scalePoints(data, scaleX, scaleY, i, 2);
i += 4 + 1;
len += 1;
break;
case U:
scalePoints(data, scaleX, scaleY, i, 2);
i += 6;
break;
}
}
},
scalePoints(data, scaleX, scaleY, start, pointCount) {
for (let i = pointCount ? start + 1 : 0, end = pointCount ? i + pointCount * 2 : data.length; i < end; i += 2) {
data[i] *= scaleX;
data[i + 1] *= scaleY;
}
}
};
const {scalePoints: scalePoints} = PathScaler;
const matrix = MatrixHelper.get();
const {topLeft: topLeft, top: top, topRight: topRight, right: right, bottom: bottom, left: left} = Direction9;
function scaleResize(leaf, scaleX, scaleY) {
if (leaf.pathInputed) {
scaleResizePath(leaf, scaleX, scaleY);
} else {
if (scaleX !== 1) leaf.width *= scaleX;
if (scaleY !== 1) leaf.height *= scaleY;
}
}
function scaleResizeFontSize(leaf, scaleX, scaleY, direction) {
let fontScale = scaleX;
if (!isUndefined(direction)) {
const layout = leaf.__layout;
let {width: width, height: height} = layout.boxBounds;
width *= scaleY - scaleX;
height *= scaleX - scaleY;
switch (direction) {
case top:
case bottom:
fontScale = scaleY;
layout.affectScaleOrRotation ? leaf.moveInner(-width / 2, 0) : leaf.x -= width / 2;
break;
case left:
case right:
layout.affectScaleOrRotation ? leaf.moveInner(0, -height / 2) : leaf.y -= height / 2;
break;
case topLeft:
case topRight:
layout.affectScaleOrRotation ? leaf.moveInner(0, -height) : leaf.y -= height;
break;
}
}
leaf.fontSize *= fontScale;
const data = leaf.__, {padding: padding, lineHeight: lineHeight, letterSpacing: letterSpacing} = data;
if (padding) leaf.padding = isArray(padding) ? padding.map(item => item * fontScale) : padding * fontScale;
if (!data.__autoWidth) leaf.width *= fontScale;
if (!data.__autoHeight) leaf.height *= fontScale;
if (isObject(lineHeight)) {
if (lineHeight.type === "px") data.lineHeight = {
type: "px",
value: lineHeight.value * fontScale
};
} else if (lineHeight) data.lineHeight = lineHeight * fontScale;
if (isObject(letterSpacing)) {
if (letterSpacing.type === "px") data.letterSpacing = {
type: "px",
value: letterSpacing.value * fontScale
};
} else if (letterSpacing) data.letterSpacing = letterSpacing * fontScale;
}
function scaleResizePath(leaf, scaleX, scaleY) {
PathScaler.scale(leaf.__.path, scaleX, scaleY);
leaf.path = leaf.__.path;
}
function scaleResizePoints(leaf, scaleX, scaleY) {
const {points: points} = leaf;
isObject(points[0]) ? points.forEach(p => {
p.x *= scaleX, p.y *= scaleY;
}) : PathScaler.scalePoints(points, scaleX, scaleY);
leaf.points = points;
}
function scaleResizeGroup(group, scaleX, scaleY) {
const {children: children} = group;
for (let i = 0; i < children.length; i++) {
matrix.a = scaleX;
matrix.d = scaleY;
children[i].transform(matrix, true);
}
}
const leaf = Leaf.prototype, tempPoint = {}, {scale: scale, toOuterPoint: toOuterPoint} = MatrixHelper;
leaf.scaleResize = function(scaleX, scaleY = scaleX, noResize, boundsType) {
const data = this;
if (noResize || data.editConfig && data.editConfig.editSize === "scale") {
data.scaleX *= scaleX;
data.scaleY *= scaleY;
} else {
const local = this.__localMatrix;
if (scaleX < 0) data.scaleX *= -1, scaleX = -scaleX, scale(local, -1, 1);
if (scaleY < 0) data.scaleY *= -1, scaleY = -scaleY, scale(local, 1, -1);
if (boundsType === "stroke") {
const {boxBounds: boxBounds, strokeBounds: strokeBounds} = this.__layout, {x: x, y: y, width: width, height: height} = strokeBounds;
tempPoint.x = (x - boxBounds.x) * (scaleX - 1);
tempPoint.y = (y - boxBounds.y) * (scaleY - 1);
toOuterPoint(local, tempPoint, tempPoint, true);
this.x += tempPoint.x;
this.y += tempPoint.y;
scaleX = (width * scaleX - (width - boxBounds.width)) / boxBounds.width;
scaleY = (height * scaleY - (height - boxBounds.height)) / boxBounds.height;
}
this.__scaleResize(scaleX, scaleY);
}
};
leaf.__scaleResize = function(scaleX, scaleY) {
scaleResize(this, scaleX, scaleY);
};
leaf.resizeWidth = function(width) {
const scale = width / this.getBounds("box", "local").width || 1;
this.scaleOf(this.__layout.boxBounds, scale, this.__.lockRatio ? scale : 1, true);
};
leaf.resizeHeight = function(height) {
const scale = height / this.getBounds("box", "local").height || 1;
this.scaleOf(this.__layout.boxBounds, this.__.lockRatio ? scale : 1, scale, true);
};
Text.prototype.__scaleResize = function(scaleX, scaleY) {
const {app: app, editConfig: editConfig} = this, editor = app && app.editor, dragPoint = editor && editor.dragPoint;
if (this.__.resizeFontSize || editConfig && editConfig.editSize === "font-size" || dragPoint && editor.mergedConfig.editSize === "font-size") {
scaleResizeFontSize(this, scaleX, scaleY, dragPoint && dragPoint.direction);
} else {
const {__autoWidth: __autoWidth, __autoHeight: __autoHeight, textAlign: textAlign, verticalAlign: verticalAlign} = this.__, {boxBounds: boxBounds} = this.__layout;
if (__autoWidth && textAlign !== "left" && scaleX !== 1) this.x += boxBounds.x;
if (__autoHeight && verticalAlign !== "top" && scaleY !== 1) this.y += boxBounds.y;
scaleResize(this, scaleX, scaleY);
}
};
Path.prototype.__scaleResize = function(scaleX, scaleY) {
scaleResizePath(this, scaleX, scaleY);
};
Line.prototype.__scaleResize = function(scaleX, scaleY) {
if (this.pathInputed) {
scaleResizePath(this, scaleX, scaleY);
} else if (this.points) {
scaleResizePoints(this, scaleX, scaleY);
} else {
this.width *= scaleX;
}
};
Polygon.prototype.__scaleResize = function(scaleX, scaleY) {
if (this.pathInputed) {
scaleResizePath(this, scaleX, scaleY);
} else if (this.points) {
scaleResizePoints(this, scaleX, scaleY);
} else {
scaleResize(this, scaleX, scaleY);
}
};
Group.prototype.__scaleResize = function(scaleX, scaleY) {
scaleResizeGroup(this, scaleX, scaleY);
};
Box.prototype.__scaleResize = function(scaleX, scaleY) {
const {resizeChildren: resizeChildren, __autoSize: __autoSize} = this.__;
if (!(__autoSize && resizeChildren)) scaleResize(this, scaleX, scaleY);
if (resizeChildren) scaleResizeGroup(this, scaleX, scaleY);
};
Plugin.add("resize");
export { PathScaler, scaleResize, scaleResizeFontSize, scaleResizeGroup, scaleResizePath, scaleResizePoints };