feat: add replayer func client side

This commit is contained in:
Rohit Rajan
2026-01-09 17:59:18 +05:30
parent d7830ee6ef
commit dddac2d966
15 changed files with 308 additions and 732 deletions

View File

@@ -59,7 +59,12 @@ class CapturedElementHighlighter {
* Get the iframe document
*/
private getIframeDocument(): Document | null {
const iframeElement = document.querySelector('#dom-browser-iframe') as HTMLIFrameElement;
let iframeElement = document.querySelector('#dom-browser-iframe') as HTMLIFrameElement;
if (!iframeElement) {
iframeElement = document.querySelector('.replayer-wrapper iframe') as HTMLIFrameElement;
}
return iframeElement?.contentDocument || null;
}

View File

@@ -1,94 +0,0 @@
import { BROWSER_DEFAULT_HEIGHT, BROWSER_DEFAULT_WIDTH } from "../constants/const";
import { getResponsiveDimensions } from "./dimensionUtils";
export class CoordinateMapper {
private canvasWidth: number;
private canvasHeight: number;
private browserWidth: number;
private browserHeight: number;
private lastBrowserRect: { left: number, top: number, right: number, bottom: number } | null = null;
private lastCanvasRect: DOMRect | null = null;
constructor() {
const dimensions = getResponsiveDimensions();
this.canvasWidth = dimensions.canvasWidth;
this.canvasHeight = dimensions.canvasHeight;
this.browserWidth = BROWSER_DEFAULT_WIDTH;
this.browserHeight = BROWSER_DEFAULT_HEIGHT;
}
mapCanvasToBrowser(coord: { x: number, y: number }): { x: number, y: number } {
return {
x: (coord.x / this.canvasWidth) * this.browserWidth,
y: (coord.y / this.canvasHeight) * this.browserHeight
};
}
mapBrowserToCanvas(coord: { x: number, y: number }): { x: number, y: number } {
return {
x: (coord.x / this.browserWidth) * this.canvasWidth,
y: (coord.y / this.browserHeight) * this.canvasHeight
};
}
mapBrowserRectToCanvas(rect: DOMRect): DOMRect {
if (this.lastBrowserRect &&
this.lastBrowserRect.left === rect.left &&
this.lastBrowserRect.top === rect.top &&
this.lastBrowserRect.right === rect.right &&
this.lastBrowserRect.bottom === rect.bottom) {
return this.lastCanvasRect!;
}
const topLeft = this.mapBrowserToCanvas({ x: rect.left, y: rect.top });
const bottomRight = this.mapBrowserToCanvas({ x: rect.right, y: rect.bottom });
const width = bottomRight.x - topLeft.x;
const height = bottomRight.y - topLeft.y;
const result = new DOMRect(
topLeft.x,
topLeft.y,
width,
height
);
this.lastBrowserRect = {
left: rect.left,
top: rect.top,
right: rect.right,
bottom: rect.bottom
};
this.lastCanvasRect = result;
return result;
}
mapCanvasRectToBrowser(rect: DOMRect): DOMRect {
const topLeft = this.mapCanvasToBrowser({ x: rect.left, y: rect.top });
const bottomRight = this.mapCanvasToBrowser({ x: rect.right, y: rect.bottom });
const width = bottomRight.x - topLeft.x;
const height = bottomRight.y - topLeft.y;
return new DOMRect(
topLeft.x,
topLeft.y,
width,
height
);
}
updateDimensions(canvasWidth?: number, canvasHeight?: number, browserWidth?: number, browserHeight?: number) {
if (canvasWidth) this.canvasWidth = canvasWidth;
if (canvasHeight) this.canvasHeight = canvasHeight;
if (browserWidth) this.browserWidth = browserWidth;
if (browserHeight) this.browserHeight = browserHeight;
this.lastBrowserRect = null;
this.lastCanvasRect = null;
}
}
export const coordinateMapper = new CoordinateMapper();

View File

@@ -1,139 +0,0 @@
import {
ONE_PERCENT_OF_VIEWPORT_H,
ONE_PERCENT_OF_VIEWPORT_W,
} from "../constants/const";
import { Coordinates } from '../components/recorder/Canvas';
export const throttle = (callback: any, limit: number) => {
let wait = false;
return (...args: any[]) => {
if (!wait) {
callback(...args);
wait = true;
setTimeout(function () {
wait = false;
}, limit);
}
}
}
export const getMappedCoordinates = (
event: MouseEvent,
canvas: HTMLCanvasElement | null,
browserWidth: number,
browserHeight: number,
): Coordinates => {
const clientCoordinates = getCoordinates(event, canvas);
const mappedX = mapPixelFromSmallerToLarger(
browserWidth / 100,
ONE_PERCENT_OF_VIEWPORT_W,
clientCoordinates.x,
);
const mappedY = mapPixelFromSmallerToLarger(
browserHeight / 100,
ONE_PERCENT_OF_VIEWPORT_H,
clientCoordinates.y,
);
return {
x: mappedX,
y: mappedY
};
};
const getCoordinates = (event: MouseEvent, canvas: HTMLCanvasElement | null): Coordinates => {
if (!canvas) {
return { x: 0, y: 0 };
}
return {
x: event.pageX - canvas.offsetLeft,
y: event.pageY - canvas.offsetTop
};
};
export const mapRect = (
rect: DOMRect,
browserWidth: number,
browserHeight: number,
) => {
const mappedX = mapPixelFromSmallerToLarger(
browserWidth / 100,
ONE_PERCENT_OF_VIEWPORT_W,
rect.x,
);
const mappedLeft = mapPixelFromSmallerToLarger(
browserWidth / 100,
ONE_PERCENT_OF_VIEWPORT_W,
rect.left,
);
const mappedRight = mapPixelFromSmallerToLarger(
browserWidth / 100,
ONE_PERCENT_OF_VIEWPORT_W,
rect.right,
);
const mappedWidth = mapPixelFromSmallerToLarger(
browserWidth / 100,
ONE_PERCENT_OF_VIEWPORT_W,
rect.width,
);
const mappedY = mapPixelFromSmallerToLarger(
browserHeight / 100,
ONE_PERCENT_OF_VIEWPORT_H,
rect.y,
);
const mappedTop = mapPixelFromSmallerToLarger(
browserHeight / 100,
ONE_PERCENT_OF_VIEWPORT_H,
rect.top,
);
const mappedBottom = mapPixelFromSmallerToLarger(
browserHeight / 100,
ONE_PERCENT_OF_VIEWPORT_H,
rect.bottom,
);
const mappedHeight = mapPixelFromSmallerToLarger(
browserHeight / 100,
ONE_PERCENT_OF_VIEWPORT_H,
rect.height,
);
console.log('Mapped:', {
x: mappedX,
y: mappedY,
width: mappedWidth,
height: mappedHeight,
top: mappedTop,
right: mappedRight,
bottom: mappedBottom,
left: mappedLeft,
})
return {
x: mappedX,
y: mappedY,
width: mappedWidth,
height: mappedHeight,
top: mappedTop,
right: mappedRight,
bottom: mappedBottom,
left: mappedLeft,
};
};
const mapPixelFromSmallerToLarger = (
onePercentOfSmallerScreen: number,
onePercentOfLargerScreen: number,
pixel: number
): number => {
const xPercentOfScreen = pixel / onePercentOfSmallerScreen;
return xPercentOfScreen * onePercentOfLargerScreen;
};
const mapPixelFromLargerToSmaller = (
onePercentOfSmallerScreen: number,
onePercentOfLargerScreen: number,
pixel: number
): number => {
const xPercentOfScreen = pixel / onePercentOfLargerScreen;
return Math.round(xPercentOfScreen * onePercentOfSmallerScreen);
};