fix(lit-components): fix rendering and interaction issues in force-graph, html-table, and draggable-dom
Build and Deploy / build-and-deploy (push) Has been cancelled
Build and Deploy / build-and-deploy (push) Has been cancelled
- lit-force-graph: Refactored for instance reuse, better lifecycle management, and added dynamic imports for AR/VR modes. - lit-html-table: Improved visual design, readability of headers, and fixed reactivity in editable mode. - lit-draggable-dom: Fixed clipping issues by switching to relative/absolute positioning and resolved a panning speed bug caused by CSS variable inheritance.
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
import { Offset } from "./utils";
|
||||
|
||||
/**
|
||||
* Matrix
|
||||
*/
|
||||
export type Matrix = number[];
|
||||
|
||||
const DEFAULT_MATRIX: Matrix = [1, 0, 0, 1, 0, 0];
|
||||
const DEFAULT_INVERSE_MATRIX: Matrix = [1, 0, 0, 1];
|
||||
|
||||
/**
|
||||
* Matrix context
|
||||
*/
|
||||
export interface MatrixContext {
|
||||
matrix: Matrix;
|
||||
inverseMatrix: Matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default matrix context
|
||||
*/
|
||||
export const defaultMatrix = createMatrix({ x: 0, y: 0 }, 1, 0);
|
||||
|
||||
/**
|
||||
* Create a matrix and inverse matrix
|
||||
*
|
||||
* @param offset - offset
|
||||
* @param scale - scale factor
|
||||
* @param rotation - in radians
|
||||
*
|
||||
* @link https://stackoverflow.com/a/34598847/7303311
|
||||
*/
|
||||
export function createMatrix(
|
||||
offset: Offset,
|
||||
scale: number,
|
||||
rotation: number
|
||||
): MatrixContext {
|
||||
const m = [...DEFAULT_MATRIX];
|
||||
const im = [...DEFAULT_INVERSE_MATRIX];
|
||||
m[3] = m[0] = Math.cos(rotation) * scale;
|
||||
m[2] = -(m[1] = Math.sin(rotation) * scale);
|
||||
m[4] = offset.x;
|
||||
m[5] = offset.y;
|
||||
const cross = m[0] * m[3] - m[1] * m[2];
|
||||
im[0] = m[3] / cross;
|
||||
im[1] = -m[1] / cross;
|
||||
im[2] = -m[2] / cross;
|
||||
im[3] = m[0] / cross;
|
||||
return {
|
||||
matrix: m,
|
||||
inverseMatrix: im,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a local offset from a global offset
|
||||
*
|
||||
* @param matrix - matrix
|
||||
* @param inverseMatrix - inverse matrix
|
||||
* @param offset - offset
|
||||
*
|
||||
* @link https://stackoverflow.com/a/34598847/7303311
|
||||
*/
|
||||
export function toWorld(context: MatrixContext, offset: Offset): Offset {
|
||||
let xx, yy, m;
|
||||
m = context.inverseMatrix;
|
||||
xx = offset.x - context.matrix[4];
|
||||
yy = offset.y - context.matrix[5];
|
||||
const localX = xx * m[0] + yy * m[2];
|
||||
const localY = xx * m[1] + yy * m[3];
|
||||
return {
|
||||
x: localX,
|
||||
y: localY,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrix info
|
||||
*
|
||||
* @param matrix - matrix
|
||||
* @returns scale, offset, rotation
|
||||
*/
|
||||
export function matrixInfo(context: MatrixContext) {
|
||||
const rotation = rotationFromMatrix(context);
|
||||
const { scale } = scaleFromMatrix(context);
|
||||
const offset = offsetFromMatrix(context);
|
||||
return {
|
||||
rotation,
|
||||
scale,
|
||||
offset,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rotation from matrix
|
||||
*
|
||||
* @param matrix - matrix
|
||||
* @returns rotation in radians
|
||||
*/
|
||||
export function rotationFromMatrix(context: MatrixContext) {
|
||||
const matrix = context.matrix;
|
||||
const rad = Math.atan2(matrix[1], matrix[0]);
|
||||
return rad;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scale factor from matrix
|
||||
*
|
||||
* @param matrix - matrix
|
||||
* @returns scale factor
|
||||
*/
|
||||
export function scaleFromMatrix(context: MatrixContext): {
|
||||
scaleX: number;
|
||||
scaleY: number;
|
||||
scale: number;
|
||||
} {
|
||||
const matrix = context.matrix;
|
||||
const scaleX = Math.sqrt(matrix[0] * matrix[0] + matrix[1] * matrix[1]);
|
||||
const scaleY = Math.sqrt(matrix[2] * matrix[2] + matrix[3] * matrix[3]);
|
||||
return {
|
||||
scaleX,
|
||||
scaleY,
|
||||
scale: Math.max(scaleX, scaleY),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get offset from matrix
|
||||
*
|
||||
* @param matrix - matrix
|
||||
* @returns offset
|
||||
*/
|
||||
export function offsetFromMatrix(context: MatrixContext) {
|
||||
const matrix = context.matrix;
|
||||
return {
|
||||
x: matrix[4],
|
||||
y: matrix[5],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply matrix to canvas
|
||||
*
|
||||
* @param ctx - canvas context
|
||||
* @param matrix - matrix
|
||||
*/
|
||||
export function applyMatrix(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
context: MatrixContext
|
||||
) {
|
||||
const m = context.matrix;
|
||||
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply default matrix to canvas
|
||||
*
|
||||
* @param ctx - canvas context
|
||||
*/
|
||||
export function applyDefaultMatrix(ctx: CanvasRenderingContext2D) {
|
||||
const m = DEFAULT_MATRIX;
|
||||
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get matrix from canvas
|
||||
*
|
||||
* @param ctx - canvas context
|
||||
* @returns Matrix context
|
||||
*/
|
||||
export function getMatrixFromCanvas(
|
||||
ctx: CanvasRenderingContext2D
|
||||
): MatrixContext {
|
||||
const transform = ctx.getTransform();
|
||||
const m = [...DEFAULT_MATRIX];
|
||||
const im = [...DEFAULT_INVERSE_MATRIX];
|
||||
m[0] = transform.a;
|
||||
m[1] = transform.b;
|
||||
m[2] = transform.c;
|
||||
m[3] = transform.d;
|
||||
m[4] = transform.e;
|
||||
m[5] = transform.f;
|
||||
const cross = m[0] * m[3] - m[1] * m[2];
|
||||
im[0] = m[3] / cross;
|
||||
im[1] = -m[1] / cross;
|
||||
im[2] = -m[2] / cross;
|
||||
im[3] = m[0] / cross;
|
||||
return {
|
||||
matrix: m,
|
||||
inverseMatrix: im,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user