@antv/x6
Version:
JavaScript diagramming library that uses SVG and HTML for rendering.
236 lines • 11.1 kB
JavaScript
import { transformPoint, createSVGMatrix, matrixToScale, matrixToRotation, matrixToTranslation, parseTransformString, transformStringToMatrix, matrixToTransformString, createSVGTransform, transformLine, transformPolyline, } from './matrix';
import { createSvgElement } from './elem';
import { Vector } from '../vector';
import { Line, Point, Polyline } from '../../geometry';
describe('Dom', () => {
describe('matrix', () => {
const fixture = document.createElement('div');
const svgContainer = Vector.create('svg').node;
fixture.appendChild(svgContainer);
document.body.appendChild(fixture);
afterAll(() => {
var _a;
(_a = fixture.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(fixture);
});
describe('createSVGTransform', () => {
it('should return SVG transform object', () => {
const svgDocument = createSvgElement('svg');
const matrix = svgDocument.createSVGMatrix();
expect(createSVGTransform(matrix)).toBeInstanceOf(SVGTransform);
expect(createSVGTransform({
a: 1,
b: 0,
c: 0,
d: 1,
e: 0,
f: 0,
})).toBeInstanceOf(SVGTransform);
});
});
describe('#transformPoint', () => {
const p = { x: 1, y: 2 };
const group = Vector.create('g');
const node = group.node;
svgContainer.appendChild(group.node);
it('should return the point unchanged when transformed without transformation', () => {
const t = transformPoint(p, node.getCTM());
expect(t.equals(p)).toBe(true);
});
it('should returns correct point when transformed with scale transformation', () => {
group.scale(2, 3);
const t = transformPoint(p, node.getCTM());
expect(t.equals({ x: 2, y: 6 })).toBe(true);
});
it('should returns correct point when transformed with rotate transformation', () => {
group.attr('transform', 'rotate(90)');
const t = transformPoint(p, node.getCTM());
expect(t.equals({ x: -2, y: 1 })).toBe(true);
});
});
describe('#transformLine', () => {
const matrix = createSVGMatrix().translate(50, 50);
const line = new Line(new Point(0, 0), new Point(10, 10));
it('should return the transformed line', () => {
const l = transformLine(line, matrix);
expect(l.start.x).toBe(50);
expect(l.start.y).toBe(50);
});
});
describe('#transformPolyline', () => {
const matrix = createSVGMatrix().translate(50, 50);
const points = [new Point(0, 0), new Point(10, 10)];
const polyline = new Polyline(points);
it('should return transformed polyline', () => {
var _a, _b;
const p = transformPolyline(polyline, matrix);
expect((_a = p.pointAt(0)) === null || _a === void 0 ? void 0 : _a.x).toBe(50);
expect((_b = p.pointAt(0)) === null || _b === void 0 ? void 0 : _b.y).toBe(50);
});
});
describe('#getTransformToElement', () => {
it('rotate', () => {
const normalizeFloat = (value) => {
const temp = value * 100;
return temp > 0 ? Math.floor(temp) : Math.ceil(temp);
};
const container = Vector.create(svgContainer);
const group = Vector.create('g');
const rect = Vector.create('rect');
container.append(group);
container.append(rect);
rect.rotate(45);
const matrix = group.getTransformToElement(rect.node);
expect({
a: normalizeFloat(matrix.a),
b: normalizeFloat(matrix.b),
c: normalizeFloat(matrix.c),
d: normalizeFloat(matrix.d),
e: normalizeFloat(matrix.e),
f: normalizeFloat(matrix.f),
}).toEqual({
a: normalizeFloat(0.7071067811865476),
b: normalizeFloat(-0.7071067811865475),
c: normalizeFloat(0.7071067811865475),
d: normalizeFloat(0.7071067811865476),
e: normalizeFloat(0),
f: normalizeFloat(0),
});
group.remove();
rect.remove();
});
it('translate', () => {
const container = Vector.create(svgContainer);
const group = Vector.create('g');
const rect = Vector.create('rect');
container.append(group);
container.append(rect);
rect.translate(10, 10);
const matrix = group.getTransformToElement(rect.node);
expect({
a: matrix.a,
b: matrix.b,
c: matrix.c,
d: matrix.d,
e: matrix.e,
f: matrix.f,
}).toEqual({
a: 1,
b: 0,
c: 0,
d: 1,
e: -10,
f: -10,
});
group.remove();
rect.remove();
});
});
describe('#parseTransformString', () => {
it('should parse scale, rotate, translate', () => {
const parsed = parseTransformString('scale(3) rotate(6) translate(9) xxx(11)');
expect(parsed.scale).toEqual({ sx: 3, sy: 3 });
expect(parsed.rotation).toEqual({
angle: 6,
cx: undefined,
cy: undefined,
});
expect(parsed.translation).toEqual({ tx: 9, ty: 0 });
});
it('should parse martix', () => {
const parsed = parseTransformString('matrix(1,0,0,1,30,30)');
expect(parsed.scale).toEqual({ sx: 1, sy: 1 });
expect(parsed.rotation).toEqual({
angle: 0,
cx: undefined,
cy: undefined,
});
expect(parsed.translation).toEqual({ tx: 30, ty: 30 });
});
});
describe('#transformStringToMatrix', () => {
let svgTestGroup;
beforeEach(() => {
svgTestGroup = Vector.create('g');
svgContainer.appendChild(svgTestGroup.node);
});
afterEach(() => {
svgTestGroup.remove();
});
const arr = [
'',
'scale(2)',
'scale(2,3)',
'scale(2.5,3.1)',
'translate(10, 10)',
'translate(10,10)',
'translate(10.2,11.6)',
'rotate(10)',
'rotate(10,100,100)',
'skewX(40)',
'skewY(60)',
'scale(2,2) matrix(1 0 0 1 10 10)',
'matrix(1 0 0 1 10 10) scale(2,2)',
'rotate(10,100,100) matrix(1 0 0 1 10 10) scale(2,2) translate(10,20)',
];
arr.forEach((transformString) => {
it(`should convert "${transformString}" to matrix`, () => {
svgTestGroup.attr('transform', transformString);
expect(transformStringToMatrix(transformString)).toEqual(svgTestGroup.node.getCTM());
});
});
});
describe('#matrixToTransformString', () => {
it('should return correct transformation string', () => {
expect(matrixToTransformString()).toEqual('matrix(1,0,0,1,0,0)');
expect(matrixToTransformString({ a: 2, d: 2 })).toEqual('matrix(2,0,0,2,0,0)');
expect(matrixToTransformString({ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 })).toEqual('matrix(1,2,3,4,5,6)');
expect(matrixToTransformString(createSVGMatrix({ a: 1, b: 2, c: 3, d: 4, e: 5, f: 6 }))).toEqual('matrix(1,2,3,4,5,6)');
expect(matrixToTransformString({ a: 0, b: 1, c: 1, d: 0, e: 0, f: 0 })).toEqual('matrix(0,1,1,0,0,0)');
});
});
describe('#matrixTo[Transformation]', () => {
function roundObject(obj) {
// eslint-disable-next-line
for (const i in obj) {
if (Object.prototype.hasOwnProperty.call(obj, i)) {
obj[i] = Math.round(obj[i]);
}
}
return obj;
}
it('should convert matrix to rotation metadata', () => {
let angle;
angle = matrixToRotation(createSVGMatrix().rotate(45));
expect(roundObject(angle)).toEqual({ angle: 45 });
angle = matrixToRotation(createSVGMatrix().translate(50, 50).rotate(15));
expect(roundObject(angle)).toEqual({ angle: 15 });
angle = matrixToRotation(createSVGMatrix().translate(50, 50).rotate(60).scale(2));
expect(roundObject(angle)).toEqual({ angle: 60 });
angle = matrixToRotation(createSVGMatrix().rotate(60).rotate(60));
expect(roundObject(angle)).toEqual({ angle: 120 });
});
it('should convert matrix to translation medata', () => {
let translate;
translate = matrixToTranslation(createSVGMatrix().translate(10, 20));
expect(roundObject(translate)).toEqual({ tx: 10, ty: 20 });
translate = matrixToTranslation(createSVGMatrix().translate(10, 20).rotate(10, 20).scale(2));
expect(roundObject(translate)).toEqual({ tx: 10, ty: 20 });
translate = matrixToTranslation(createSVGMatrix().translate(10, 20).translate(30, 40));
expect(roundObject(translate)).toEqual({ tx: 40, ty: 60 });
});
it('should convert matrix to scaling metadata', () => {
let scale;
scale = matrixToScale(createSVGMatrix().scale(2));
expect(roundObject(scale)).toEqual({ sx: 2, sy: 2 });
scale = matrixToScale(createSVGMatrix()
.translate(15, 15)
.scaleNonUniform(2, 3)
.rotate(10, 20));
expect(roundObject(scale)).toEqual({ sx: 2, sy: 3 });
scale = matrixToScale(createSVGMatrix().scale(2, 2).scale(3, 3));
expect(roundObject(scale)).toEqual({ sx: 6, sy: 6 });
});
});
});
});
//# sourceMappingURL=matrix.test.js.map