All files / svg-transform svg-rotate-by.ts

100% Statements 3/3
100% Branches 3/3
100% Functions 2/2
100% Lines 3/3

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30                                                5x 7x 7x      
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);
  });
}