Skip to content

svgScaleBy function ​

An order of applySvgTransforms that enlarges or shrinks the element in its own axes, around an anchor of its drawing, which gives the direction: with 'left', it grows to the right; with 'bottom', upwards.

ts
import { svgScaleBy } from 'utils';

Signature ​

ts
export function svgScaleBy(
  scaleX: number,
  scaleY = scaleX,
  anchor: Anchor = 'center',
): SvgTransformOrder<[scaleX: number, scaleY?: number, anchor?: Anchor]>

Parameters ​

NameDescription
scaleXThe factor along its width: 2 doubles it.
scaleYThe factor along its height. Defaults to scaleX.
anchorThe point of its drawing that stays in place. Defaults to 'center'.

Returns ​

The order, to change with set(scaleX, scaleY, anchor).

Example ​

ts
const level = svgScaleBy(1, 0, 'bottom');
applySvgTransforms(tankLevel, [level]);
level.set(1, 0.75, 'bottom'); // filled to 75 %, from the bottom

Tests ​

Line coverage: 100 %.

  • ✅ grows from the bottom anchor
  • ✅ grows from the left anchor
  • ✅ grows from the right anchor
  • ✅ scales both axes around the center by default

Source ​

src/svg-transform/svg-scale-by.ts (on GitHub)

Uses ​

  • Anchor: One of the 9 points of a box: its corners, the middles of its sides, its 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-scale-by.ts imports, directly or not:

Source code
ts
import type { Anchor } from './anchor';
import { createMatrix, createOrder, getAnchorPoint, inOwnAxes } from './internal';
import type { SvgTransformOrder } from './svg-transform-order';

/**
 * An order of `applySvgTransforms` that enlarges or shrinks the element in its own axes, around an anchor of
 * its drawing, which gives the direction: with `'left'`, it grows to the right; with `'bottom'`, upwards.
 *
 * @param scaleX - The factor along its width: `2` doubles it.
 * @param scaleY - The factor along its height. Defaults to `scaleX`.
 * @param anchor - The point of its drawing that stays in place. Defaults to `'center'`.
 * @returns The order, to change with `set(scaleX, scaleY, anchor)`.
 * @example
 * const level = svgScaleBy(1, 0, 'bottom');
 * applySvgTransforms(tankLevel, [level]);
 * level.set(1, 0.75, 'bottom'); // filled to 75 %, from the bottom
 */
export function svgScaleBy(
  scaleX: number,
  scaleY = scaleX,
  anchor: Anchor = 'center',
): SvgTransformOrder<[scaleX: number, scaleY?: number, anchor?: Anchor]> {
  return createOrder([scaleX, scaleY, anchor], (element, screen, sx, sy = sx, point = 'center') => {
    const { x, y } = getAnchorPoint(element.getBBox(), point);
    return inOwnAxes(screen, createMatrix(element, [sx, 0, 0, sy, x * (1 - sx), y * (1 - sy)]));
  });
}
Test file
ts
import { applySvgTransforms } from './apply-svg-transforms';
import { svgScaleBy } from './svg-scale-by';
import { describeOnScreen, renderSvg } from './testing';

describe(svgScaleBy, () => {
  it.for([
    ['bottom', 1, 1.5, { x: 10, y: 30, width: 20, height: 60 }],
    ['left', 2, 1, { x: 10, y: 50, width: 40, height: 40 }],
    ['right', 2, 1, { x: -10, y: 50, width: 40, height: 40 }],
  ] as const)('grows from the %s anchor', ([anchor, scaleX, scaleY, expected]) => {
    const byId = renderSvg('<rect id="tank" x="10" y="50" width="20" height="40" />');
    applySvgTransforms(byId('tank'), [svgScaleBy(scaleX, scaleY, anchor)]);
    expect(describeOnScreen(byId('tank'))).toMatchObject(expected);
  });

  it('scales both axes around the center by default', () => {
    const byId = renderSvg('<rect id="tank" x="10" y="10" width="20" height="20" />');
    applySvgTransforms(byId('tank'), [svgScaleBy(2)]);
    expect(describeOnScreen(byId('tank'))).toMatchObject({ x: 0, y: 0, width: 40, height: 40 });
  });
});

Keywords: svg, scale, by, svg transforms, function

Generated from the JSDoc of the sources.