svgRotateBy function
An order of applySvgTransforms that turns the element by an angle from its position before this order, clockwise on screen, around an anchor of itself or of another element: set(90) after set(3) gives 90° from the start, not 93°.
ts
import { svgRotateBy } from 'utils';Signature
ts
export function svgRotateBy(
angleDegrees: number,
anchor: Anchor = 'center',
reference?: SVGGraphicsElement,
): SvgTransformOrder<[angleDegrees: number, anchor?: Anchor, reference?: SVGGraphicsElement]>Parameters
| Name | Description |
|---|---|
angleDegrees | The rotation, in degrees. |
anchor | The point that stays in place. Defaults to 'center'. |
reference | The element giving the anchor, in any group. Defaults to the element itself. |
Returns
The order, to change with set(angleDegrees, anchor, reference).
Example
ts
const rotation = svgRotateBy(0, 'center', hub);
applySvgTransforms(needle, [rotation]);
rotation.set(30, 'center', hub); // 30° around the hub, from where it was drawnTests
Line coverage: 100 %.
- ✅ turns from its position before the order, not from the previous value
- ✅ turns from the default position given by its groups
- ✅ turns around an anchor of another element
Source
src/svg-transform/svg-rotate-by.ts (on GitHub)
Uses
Anchor: One of the 9 points of a box: its corners, the middles of its sides, its center.getSvgAnchorPoint: Finds an anchor of the box an SVG element takes on screen: a corner, the middle of a side or the center.SvgTransformOrder: An order ofapplySvgTransforms, created bysvgRotateBy,svgRotateTo,svgFlipTo,svgScaleBy,svgTranslateByorsvgPlaceOn: keep it to change its values later withset.
Files it needs
src/svg-transform/svg-rotate-by.ts imports, directly or not:
src/svg-transform/anchor.tssrc/svg-transform/get-svg-anchor-point.tssrc/svg-transform/internal/create-matrix.tssrc/svg-transform/internal/create-order.tssrc/svg-transform/internal/get-anchor-point.tssrc/svg-transform/internal/get-owner-svg.tssrc/svg-transform/internal/order-states.tssrc/svg-transform/svg-transform-order.ts
Source code
ts
import type { Anchor } from './anchor';
import { getSvgAnchorPoint } from './get-svg-anchor-point';
import { createMatrix, createOrder } from './internal';
import type { SvgTransformOrder } from './svg-transform-order';
/**
* An order of `applySvgTransforms` that turns the element by an angle from its position before this order,
* clockwise on screen, around an anchor of itself or of another element: `set(90)` after `set(3)` gives 90°
* from the start, not 93°.
*
* @param angleDegrees - The rotation, in degrees.
* @param anchor - The point that stays in place. Defaults to `'center'`.
* @param reference - The element giving the anchor, in any group. Defaults to the element itself.
* @returns The order, to change with `set(angleDegrees, anchor, reference)`.
* @example
* const rotation = svgRotateBy(0, 'center', hub);
* applySvgTransforms(needle, [rotation]);
* rotation.set(30, 'center', hub); // 30° around the hub, from where it was drawn
*/
export function svgRotateBy(
angleDegrees: number,
anchor: Anchor = 'center',
reference?: SVGGraphicsElement,
): SvgTransformOrder<[angleDegrees: number, anchor?: Anchor, reference?: SVGGraphicsElement]> {
return createOrder([angleDegrees, anchor, reference], (element, _screen, angle, point, other) => {
const { x, y } = getSvgAnchorPoint(other ?? element, point);
return createMatrix(element).translate(x, y).rotate(angle).translate(-x, -y);
});
}Test file
ts
import { applySvgTransforms } from './apply-svg-transforms';
import { svgRotateBy } from './svg-rotate-by';
import { describeOnScreen, renderSvg } from './testing';
describe(svgRotateBy, () => {
it('turns from its position before the order, not from the previous value', () => {
const byId = renderSvg('<rect id="flag" transform="rotate(30 50 50)" x="40" y="45" width="20" height="10" />');
const rotation = svgRotateBy(3);
applySvgTransforms(byId('flag'), [rotation]);
rotation.set(90);
expect(describeOnScreen(byId('flag'))).toMatchObject({ rotation: 120 });
});
it('turns from the default position given by its groups', () => {
const byId = renderSvg(
'<g transform="rotate(90 50 50)"><rect id="bar" x="40" y="45" width="20" height="10" /></g>',
);
applySvgTransforms(byId('bar'), [svgRotateBy(90)]);
expect(describeOnScreen(byId('bar'))).toMatchObject({ x: 40, y: 45, width: 20, height: 10, rotation: 180 });
});
it('turns around an anchor of another element', () => {
const byId = renderSvg(
'<rect id="needle" x="98" y="60" width="4" height="40" /><circle id="hub" cx="100" cy="100" r="5" />',
);
applySvgTransforms(byId('needle'), [svgRotateBy(90, 'center', byId('hub'))]);
expect(describeOnScreen(byId('needle'))).toMatchObject({ x: 100, y: 98, width: 40, height: 4, rotation: 90 });
});
});Keywords: svg, rotate, by, svg transforms, function