Skip to content

svgFlipTo function ​

An order of applySvgTransforms that makes the element mirrored or not, as seen on screen, around one of its anchors: svgFlipTo(false) makes a mirrored text readable again.

ts
import { svgFlipTo } from 'utils';

Signature ​

ts
export function svgFlipTo(
  isFlipped = true,
  axis: 'horizontal' | 'vertical' = 'horizontal',
  anchor: Anchor = 'center',
): SvgTransformOrder<[isFlipped?: boolean, axis?: 'horizontal' | 'vertical', anchor?: Anchor]>

Parameters ​

NameDescription
isFlippedWhether the element must look mirrored. Defaults to true.
axisThe mirror used when the state changes: 'horizontal' swaps left and right, 'vertical' top and bottom. Defaults to 'horizontal'.
anchorThe point of the element that stays in place. Defaults to 'center'.

Returns ​

The order, to change with set(isFlipped, axis, anchor).

Example ​

ts
const flip = svgFlipTo(false);
applySvgTransforms(valve, [flip]);
flip.set(true); // facing the other way, same place

Tests ​

Line coverage: 100 %.

  • ✅ mirrors horizontally around the center by default
  • ✅ mirrors vertically around an anchor
  • ✅ makes the element mirrored: true, from scale(-1 1) translate(-40 0)
  • ✅ makes the element mirrored: false, from translate(0 0)
  • ✅ makes the element mirrored: false, from scale(-1 1) translate(-40 0)

Source ​

src/svg-transform/svg-flip-to.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 of applySvgTransforms, created by svgRotateBy, svgRotateTo, svgFlipTo, svgScaleBy, svgTranslateBy or svgPlaceOn: keep it to change its values later with set.

Files it needs ​

src/svg-transform/svg-flip-to.ts imports, directly or not:

Source code
ts
import type { Anchor } from './anchor';
import { getSvgAnchorPoint } from './get-svg-anchor-point';
import { createMatrix, createOrder, isMirrored } from './internal';
import type { SvgTransformOrder } from './svg-transform-order';

/**
 * An order of `applySvgTransforms` that makes the element mirrored or not, as seen on screen, around one of
 * its anchors: `svgFlipTo(false)` makes a mirrored text readable again.
 *
 * @param isFlipped - Whether the element must look mirrored. Defaults to `true`.
 * @param axis - The mirror used when the state changes: `'horizontal'` swaps left and right, `'vertical'` top
 * and bottom. Defaults to `'horizontal'`.
 * @param anchor - The point of the element that stays in place. Defaults to `'center'`.
 * @returns The order, to change with `set(isFlipped, axis, anchor)`.
 * @example
 * const flip = svgFlipTo(false);
 * applySvgTransforms(valve, [flip]);
 * flip.set(true); // facing the other way, same place
 */
export function svgFlipTo(
  isFlipped = true,
  axis: 'horizontal' | 'vertical' = 'horizontal',
  anchor: Anchor = 'center',
): SvgTransformOrder<[isFlipped?: boolean, axis?: 'horizontal' | 'vertical', anchor?: Anchor]> {
  return createOrder(
    [isFlipped, axis, anchor],
    (element, screen, flipped = true, mirror = 'horizontal', point = 'center') => {
      if (isMirrored(screen) === flipped) {
        return createMatrix(element);
      }
      const { x, y } = getSvgAnchorPoint(element, point);
      return createMatrix(element, mirror === 'horizontal' ? [-1, 0, 0, 1, 2 * x, 0] : [1, 0, 0, -1, 0, 2 * y]);
    },
  );
}
Test file
ts
import { applySvgTransforms } from './apply-svg-transforms';
import { svgFlipTo } from './svg-flip-to';
import { describeOnScreen, renderSvg } from './testing';

describe(svgFlipTo, () => {
  it('mirrors horizontally around the center by default', () => {
    const byId = renderSvg(
      '<g transform="rotate(30 50 50)"><rect id="valve" x="40" y="45" width="20" height="10" /></g>',
    );
    const before = describeOnScreen(byId('valve'));
    applySvgTransforms(byId('valve'), [svgFlipTo()]);
    expect(describeOnScreen(byId('valve'))).toMatchObject({ x: before.x, y: before.y, isFlipped: true });
  });

  it('mirrors vertically around an anchor', () => {
    const byId = renderSvg('<rect id="valve" x="10" y="10" width="20" height="10" />');
    applySvgTransforms(byId('valve'), [svgFlipTo(true, 'vertical', 'top')]);
    expect(describeOnScreen(byId('valve'))).toMatchObject({ x: 10, y: 0, isFlipped: true });
  });

  it.for([
    [true, 'scale(-1 1) translate(-40 0)', true],
    [false, 'translate(0 0)', false],
    [false, 'scale(-1 1) translate(-40 0)', false],
  ] as const)('makes the element mirrored: %s, from %s', ([isFlipped, transform, expected]) => {
    const byId = renderSvg(`<rect id="label" transform="${transform}" x="10" y="10" width="20" height="10" />`);
    applySvgTransforms(byId('label'), [svgFlipTo(isFlipped)]);
    expect(describeOnScreen(byId('label'))).toMatchObject({ x: 10, y: 10, isFlipped: expected });
  });
});

Keywords: svg, flip, to, svg transforms, function

Generated from the JSDoc of the sources.