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 31 32 33 34 35 36 37 38 39 | 26x 26x 32x 31x 26x 31x 31x 34x 34x 34x 14x 34x 34x 34x 31x | import { createMatrix, getOrderState, getOwnerSvg, getScreenMatrix } from './internal';
import type { SvgTransformOrder } from './svg-transform-order';
/**
* Applies orders to an SVG element, in order, each on what the previous ones give: one transform per order
* is added at the end of its `transform` list. Changing an order later with `set` updates its own transform
* only, from what the element shows without it.
*
* @param element - A rendered SVG element.
* @param orders - The orders, such as `svgRotateTo(0)`, `svgPlaceOn(target)`, `svgRotateBy(0)`.
* @throws {TypeError} When the element is not rendered or not inside an `<svg>`, or an order was not created
* by an order function.
* @example
* const rotation = svgRotateBy(0);
* applySvgTransforms(needle, [svgPlaceOn(hub, 'center', 'bottom'), rotation]);
* rotation.set(45); // at each frame: 45° more than its first position
*/
export function applySvgTransforms(element: SVGGraphicsElement, orders: readonly SvgTransformOrder<never>[]): void {
const svg = getOwnerSvg(element);
const steps = orders
.map((order) => getOrderState(order))
.map((state) => ({ state, transform: element.transform.baseVal.appendItem(svg.createSVGTransform()) }));
for (const [index, { state, transform }] of steps.entries()) {
const later = steps.slice(index + 1);
state.update = (): void => {
transform.setMatrix(createMatrix(element));
let after = createMatrix(element);
for (const next of later) {
after = after.multiply(next.transform.matrix);
}
const screen = getScreenMatrix(element);
const change = state.toChange(element, screen);
transform.setMatrix(after.multiply(screen.inverse()).multiply(change).multiply(screen).multiply(after.inverse()));
};
state.update();
}
}
|