Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
const parts = transform.split(/\(\s*/);
const command = parts[0].trim();
const v = parts[1].split(/[\s,]+/g);
// Convert values to floats
for (let j = 0; j < v.length; j++) {
v[j] = parseFloat(v[j]);
}
switch (command) {
case 'matrix':
matrix = Matrix.compose(matrix, {a: v[0], b: v[1], c: v[2], d: v[3], e: v[4], f: v[5]});
break;
case 'rotate':
matrix = Matrix.compose(matrix, Matrix.rotateDEG(v[0], v[1] || 0, v[2] || 0));
break;
case 'translate':
matrix = Matrix.compose(matrix, Matrix.translate(v[0], v[1] || 0));
break;
case 'scale':
matrix = Matrix.compose(matrix, Matrix.scale(v[0], v[1] || v[0]));
break;
case 'skewX':
matrix = Matrix.compose(matrix, Matrix.skewDEG(v[0], 0));
break;
case 'skewY':
matrix = Matrix.compose(matrix, Matrix.skewDEG(0, v[0]));
break;
default:
log.error(`Couldn't parse: ${command}`);
}
}
return matrix;
};
const _parseTransform = function (domElement) {
let matrix = Matrix.identity();
const string = domElement.attributes && domElement.attributes.transform && domElement.attributes.transform.value;
if (!string) return matrix;
// https://www.w3.org/TR/SVG/types.html#DataTypeTransformList
// Parse SVG transform string. First we split at /)\s*/, to separate
// commands
const transforms = string.split(/\)\s*/g);
for (const transform of transforms) {
if (!transform) break;
// Command come before the '(', values after
const parts = transform.split(/\(\s*/);
const command = parts[0].trim();
const v = parts[1].split(/[\s,]+/g);
// Convert values to floats
for (let j = 0; j < v.length; j++) {
v[j] = parseFloat(v[j]);
}
export function fitSelection(value, selectionSVGPointX, selectionSVGPointY, selectionWidth, selectionHeight) {
let {viewerWidth, viewerHeight} = value;
let scaleX = viewerWidth / selectionWidth;
let scaleY = viewerHeight / selectionHeight;
let scaleLevel = Math.min(scaleX, scaleY);
const matrix = transform(
scale(scaleLevel, scaleLevel), //2
translate(-selectionSVGPointX, -selectionSVGPointY) //1
);
if(isZoomLevelGoingOutOfBounds(value, scaleLevel / value.d)) {
// Do not allow scale and translation
return set(value, {
mode: MODE_IDLE,
startX: null,
startY: null,
endX: null,
endY: null
});
}
return set(value, {
mode: MODE_IDLE,
...limitZoomLevel(value, matrix),
const previousPointDistance = hasPinchPointDistance(value) ? value.pinchPointDistance : pinchPointDistance;
const svgPoint = getSVGPoint(value, (x1 + x2) / 2, (y1 + y2) / 2);
let distanceFactor = pinchPointDistance/previousPointDistance;
if (isZoomLevelGoingOutOfBounds(value, distanceFactor)) {
// Do not change translation and scale of value
return value;
}
if (event.cancelable) {
event.preventDefault();
}
let matrix = transform(
fromObject(value),
translate(svgPoint.x, svgPoint.y),
scale(distanceFactor, distanceFactor),
translate(-svgPoint.x, -svgPoint.y)
);
return set(value, set({
mode: MODE_ZOOMING,
...limitZoomLevel(value, matrix),
startX: null,
startY: null,
endX: null,
endY: null,
prePinchMode: value.prePinchMode ? value.prePinchMode : value.mode,
pinchPointDistance
}));
}
let distanceFactor = pinchPointDistance/previousPointDistance;
if (isZoomLevelGoingOutOfBounds(value, distanceFactor)) {
// Do not change translation and scale of value
return value;
}
if (event.cancelable) {
event.preventDefault();
}
let matrix = transform(
fromObject(value),
translate(svgPoint.x, svgPoint.y),
scale(distanceFactor, distanceFactor),
translate(-svgPoint.x, -svgPoint.y)
);
return set(value, set({
mode: MODE_ZOOMING,
...limitZoomLevel(value, matrix),
startX: null,
startY: null,
endX: null,
endY: null,
prePinchMode: value.prePinchMode ? value.prePinchMode : value.mode,
pinchPointDistance
}));
}
export function pan(value, SVGDeltaX, SVGDeltaY, panLimit = undefined) {
let matrix = transform(
fromObject(value), //2
translate(SVGDeltaX, SVGDeltaY) //1
);
// apply pan limits
if (panLimit) {
let [{x: x1, y: y1}, {x: x2, y: y2}] = applyToPoints(matrix, [
{x: value.SVGMinX + panLimit, y: value.SVGMinY + panLimit},
{x: value.SVGMinX + value.SVGWidth - panLimit, y: value.SVGMinY + value.SVGHeight - panLimit}
]);
//x limit
let moveX = 0;
if (value.viewerWidth - x1 < 0)
moveX = value.viewerWidth - x1;
else if (x2 < 0) moveX = -x2;
const y2 = event.touches[1].clientY - Math.round(top);
const pinchPointDistance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
const previousPointDistance = hasPinchPointDistance(value) ? value.pinchPointDistance : pinchPointDistance;
const svgPoint = getSVGPoint(value, (x1 + x2) / 2, (y1 + y2) / 2);
let distanceFactor = pinchPointDistance/previousPointDistance;
if (isZoomLevelGoingOutOfBounds(value, distanceFactor)) {
// Do not change translation and scale of value
return value;
}
if (event.cancelable) {
event.preventDefault();
}
let matrix = transform(
fromObject(value),
translate(svgPoint.x, svgPoint.y),
scale(distanceFactor, distanceFactor),
translate(-svgPoint.x, -svgPoint.y)
);
return set(value, set({
mode: MODE_ZOOMING,
...limitZoomLevel(value, matrix),
startX: null,
startY: null,
endX: null,
endY: null,
prePinchMode: value.prePinchMode ? value.prePinchMode : value.mode,
pinchPointDistance
}));
export function fitSelection(value, selectionSVGPointX, selectionSVGPointY, selectionWidth, selectionHeight) {
let {viewerWidth, viewerHeight} = value;
let scaleX = viewerWidth / selectionWidth;
let scaleY = viewerHeight / selectionHeight;
let scaleLevel = Math.min(scaleX, scaleY);
const matrix = transform(
scale(scaleLevel, scaleLevel), //2
translate(-selectionSVGPointX, -selectionSVGPointY) //1
);
if(isZoomLevelGoingOutOfBounds(value, scaleLevel / value.d)) {
// Do not allow scale and translation
return set(value, {
mode: MODE_IDLE,
startX: null,
startY: null,
endX: null,
endY: null
});
}
return set(value, {
export function pan(value, SVGDeltaX, SVGDeltaY) {
var panLimit = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : undefined;
var matrix = transform(fromObject(value), //2
translate(SVGDeltaX, SVGDeltaY) //1
);
// apply pan limits
if (panLimit) {
var _applyToPoints = applyToPoints(matrix, [{ x: panLimit, y: panLimit }, { x: value.SVGWidth - panLimit, y: value.SVGHeight - panLimit }]),
_applyToPoints2 = _slicedToArray(_applyToPoints, 2),
_applyToPoints2$ = _applyToPoints2[0],
x1 = _applyToPoints2$.x,
y1 = _applyToPoints2$.y,
_applyToPoints2$2 = _applyToPoints2[1],
x2 = _applyToPoints2$2.x,
y2 = _applyToPoints2$2.y;
//x limit
if (focal) focal = Matrix.applyToPoint(matrix, focal);
} else {
const dot = (a, b) => (a.x * b.x) + (a.y * b.y);
const multiply = (coefficient, v) => ({x: coefficient * v.x, y: coefficient * v.y});
const add = (a, b) => ({x: a.x + b.x, y: a.y + b.y});
const subtract = (a, b) => ({x: a.x - b.x, y: a.y - b.y});
// The line through origin and gradientPerpendicular is the line at which the gradient starts
let gradientPerpendicular = Math.abs(origin.x - destination.x) < 1e-8 ?
add(origin, {x: 1, y: (origin.x - destination.x) / (destination.y - origin.y)}) :
add(origin, {x: (destination.y - origin.y) / (origin.x - destination.x), y: 1});
// Transform points
gradientPerpendicular = Matrix.applyToPoint(matrix, gradientPerpendicular);
origin = Matrix.applyToPoint(matrix, origin);
destination = Matrix.applyToPoint(matrix, destination);
// Calculate the direction that the gradient has changed to
const originToPerpendicular = subtract(gradientPerpendicular, origin);
const originToDestination = subtract(destination, origin);
const gradientDirection = Math.abs(originToPerpendicular.x) < 1e-8 ?
{x: 1, y: -originToPerpendicular.x / originToPerpendicular.y} :
{x: -originToPerpendicular.y / originToPerpendicular.x, y: 1};
// Set the destination so that the gradient moves in the correct direction, by projecting the destination vector
// onto the gradient direction vector
const projectionCoeff = dot(originToDestination, gradientDirection) / dot(gradientDirection, gradientDirection);
const projection = multiply(projectionCoeff, gradientDirection);
destination = {x: origin.x + projection.x, y: origin.y + projection.y};
}
// Put values back into svg