feat: add replayer func client side
This commit is contained in:
310
legacy/src/Canvas.tsx
Normal file
310
legacy/src/Canvas.tsx
Normal file
@@ -0,0 +1,310 @@
|
||||
import React, { memo, useCallback, useEffect, useRef } from 'react';
|
||||
import { useSocketStore } from '../../context/socket';
|
||||
import { useGlobalInfoStore } from "../../context/globalInfo";
|
||||
import { useActionContext } from '../../context/browserActions';
|
||||
import DatePicker from '../pickers/DatePicker';
|
||||
import Dropdown from '../pickers/Dropdown';
|
||||
import TimePicker from '../pickers/TimePicker';
|
||||
import DateTimeLocalPicker from '../pickers/DateTimeLocalPicker';
|
||||
import { coordinateMapper } from '../../helpers/coordinateMapper';
|
||||
|
||||
interface CreateRefCallback {
|
||||
(ref: React.RefObject<HTMLCanvasElement>): void;
|
||||
}
|
||||
|
||||
interface CanvasProps {
|
||||
width: number;
|
||||
height: number;
|
||||
onCreateRef: CreateRefCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interface for mouse's x,y coordinates
|
||||
*/
|
||||
export interface Coordinates {
|
||||
x: number;
|
||||
y: number;
|
||||
};
|
||||
|
||||
const Canvas = ({ width, height, onCreateRef }: CanvasProps) => {
|
||||
|
||||
const canvasRef = useRef<HTMLCanvasElement>(null);
|
||||
const contextRef = useRef<CanvasRenderingContext2D | null>(null);
|
||||
const imageDataRef = useRef<ImageData | null>(null);
|
||||
const animationFrameRef = useRef<number | null>(null);
|
||||
|
||||
const { socket } = useSocketStore();
|
||||
const { setLastAction, lastAction } = useGlobalInfoStore();
|
||||
const { getText, getList } = useActionContext();
|
||||
const getTextRef = useRef(getText);
|
||||
const getListRef = useRef(getList);
|
||||
|
||||
const MOUSE_MOVE_THROTTLE = 8;
|
||||
const lastMouseMoveTime = useRef(0);
|
||||
|
||||
const [datePickerInfo, setDatePickerInfo] = React.useState<{
|
||||
coordinates: Coordinates;
|
||||
selector: string;
|
||||
} | null>(null);
|
||||
|
||||
const [dropdownInfo, setDropdownInfo] = React.useState<{
|
||||
coordinates: Coordinates;
|
||||
selector: string;
|
||||
options: Array<{
|
||||
value: string;
|
||||
text: string;
|
||||
disabled: boolean;
|
||||
selected: boolean;
|
||||
}>;
|
||||
} | null>(null);
|
||||
|
||||
const [timePickerInfo, setTimePickerInfo] = React.useState<{
|
||||
coordinates: Coordinates;
|
||||
selector: string;
|
||||
} | null>(null);
|
||||
|
||||
const [dateTimeLocalInfo, setDateTimeLocalInfo] = React.useState<{
|
||||
coordinates: Coordinates;
|
||||
selector: string;
|
||||
} | null>(null);
|
||||
|
||||
const notifyLastAction = (action: string) => {
|
||||
if (lastAction !== action) {
|
||||
setLastAction(action);
|
||||
}
|
||||
};
|
||||
|
||||
const lastMousePosition = useRef<Coordinates>({ x: 0, y: 0 });
|
||||
|
||||
useEffect(() => {
|
||||
if (canvasRef.current && !contextRef.current) {
|
||||
const ctx = canvasRef.current.getContext('2d', {
|
||||
alpha: false,
|
||||
desynchronized: true,
|
||||
willReadFrequently: false
|
||||
});
|
||||
|
||||
if (ctx) {
|
||||
contextRef.current = ctx;
|
||||
|
||||
imageDataRef.current = ctx.createImageData(width, height);
|
||||
}
|
||||
}
|
||||
}, [width, height]);
|
||||
|
||||
useEffect(() => {
|
||||
getTextRef.current = getText;
|
||||
getListRef.current = getList;
|
||||
}, [getText, getList]);
|
||||
|
||||
useEffect(() => {
|
||||
if (socket) {
|
||||
const handleDatePicker = (info: { coordinates: Coordinates, selector: string }) => {
|
||||
const canvasCoords = coordinateMapper.mapBrowserToCanvas(info.coordinates);
|
||||
setDatePickerInfo({ ...info, coordinates: canvasCoords });
|
||||
};
|
||||
|
||||
const handleDropdown = (info: {
|
||||
coordinates: Coordinates,
|
||||
selector: string,
|
||||
options: Array<{ value: string; text: string; disabled: boolean; selected: boolean; }>;
|
||||
}) => {
|
||||
const canvasCoords = coordinateMapper.mapBrowserToCanvas(info.coordinates);
|
||||
setDropdownInfo({ ...info, coordinates: canvasCoords });
|
||||
};
|
||||
|
||||
const handleTimePicker = (info: { coordinates: Coordinates, selector: string }) => {
|
||||
const canvasCoords = coordinateMapper.mapBrowserToCanvas(info.coordinates);
|
||||
setTimePickerInfo({ ...info, coordinates: canvasCoords });
|
||||
};
|
||||
|
||||
const handleDateTimePicker = (info: { coordinates: Coordinates, selector: string }) => {
|
||||
const canvasCoords = coordinateMapper.mapBrowserToCanvas(info.coordinates);
|
||||
setDateTimeLocalInfo({ ...info, coordinates: canvasCoords });
|
||||
};
|
||||
|
||||
socket.on('showDatePicker', handleDatePicker);
|
||||
socket.on('showDropdown', handleDropdown);
|
||||
socket.on('showTimePicker', handleTimePicker);
|
||||
socket.on('showDateTimePicker', handleDateTimePicker);
|
||||
|
||||
return () => {
|
||||
socket.off('showDatePicker', handleDatePicker);
|
||||
socket.off('showDropdown', handleDropdown);
|
||||
socket.off('showTimePicker', handleTimePicker);
|
||||
socket.off('showDateTimePicker', handleDateTimePicker);
|
||||
};
|
||||
}
|
||||
}, [socket]);
|
||||
|
||||
const onMouseEvent = useCallback((event: MouseEvent) => {
|
||||
if (!socket || !canvasRef.current) return;
|
||||
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const clickCoordinates = {
|
||||
x: event.clientX - rect.left,
|
||||
y: event.clientY - rect.top,
|
||||
};
|
||||
|
||||
const browserCoordinates = coordinateMapper.mapCanvasToBrowser(clickCoordinates);
|
||||
|
||||
switch (event.type) {
|
||||
case 'mousedown':
|
||||
if (getTextRef.current === true) {
|
||||
console.log('Capturing Text...');
|
||||
} else if (getListRef.current === true) {
|
||||
console.log('Capturing List...');
|
||||
} else {
|
||||
socket.emit('input:mousedown', browserCoordinates);
|
||||
}
|
||||
notifyLastAction('click');
|
||||
break;
|
||||
|
||||
case 'mousemove': {
|
||||
const now = performance.now();
|
||||
if (now - lastMouseMoveTime.current < MOUSE_MOVE_THROTTLE) {
|
||||
return;
|
||||
}
|
||||
lastMouseMoveTime.current = now;
|
||||
|
||||
const dx = Math.abs(lastMousePosition.current.x - clickCoordinates.x);
|
||||
const dy = Math.abs(lastMousePosition.current.y - clickCoordinates.y);
|
||||
|
||||
if (dx > 0.5 || dy > 0.5) {
|
||||
lastMousePosition.current = clickCoordinates;
|
||||
socket.emit('input:mousemove', browserCoordinates);
|
||||
notifyLastAction('move');
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'wheel': {
|
||||
const wheelEvent = event as WheelEvent;
|
||||
const deltaX = Math.round(wheelEvent.deltaX / 5) * 5;
|
||||
const deltaY = Math.round(wheelEvent.deltaY / 5) * 5;
|
||||
|
||||
if (Math.abs(deltaX) > 2 || Math.abs(deltaY) > 2) {
|
||||
socket.emit('input:wheel', { deltaX, deltaY });
|
||||
notifyLastAction('scroll');
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}, [socket, notifyLastAction]);
|
||||
|
||||
const onKeyboardEvent = useCallback((event: KeyboardEvent) => {
|
||||
if (socket) {
|
||||
const browserCoordinates = coordinateMapper.mapCanvasToBrowser(lastMousePosition.current);
|
||||
|
||||
switch (event.type) {
|
||||
case 'keydown':
|
||||
socket.emit('input:keydown', { key: event.key, coordinates: browserCoordinates });
|
||||
notifyLastAction(`${event.key} pressed`);
|
||||
break;
|
||||
case 'keyup':
|
||||
socket.emit('input:keyup', event.key);
|
||||
break;
|
||||
default:
|
||||
console.log('Default keyEvent registered');
|
||||
return;
|
||||
}
|
||||
}
|
||||
}, [socket, notifyLastAction]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
|
||||
onCreateRef(canvasRef);
|
||||
|
||||
const options = { passive: true };
|
||||
|
||||
canvas.addEventListener('mousedown', onMouseEvent, options);
|
||||
canvas.addEventListener('mousemove', onMouseEvent, options);
|
||||
canvas.addEventListener('wheel', onMouseEvent, options);
|
||||
canvas.addEventListener('keydown', onKeyboardEvent);
|
||||
canvas.addEventListener('keyup', onKeyboardEvent);
|
||||
|
||||
return () => {
|
||||
canvas.removeEventListener('mousedown', onMouseEvent);
|
||||
canvas.removeEventListener('mousemove', onMouseEvent);
|
||||
canvas.removeEventListener('wheel', onMouseEvent);
|
||||
canvas.removeEventListener('keydown', onKeyboardEvent);
|
||||
canvas.removeEventListener('keyup', onKeyboardEvent);
|
||||
};
|
||||
}, [onMouseEvent, onKeyboardEvent, onCreateRef]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (animationFrameRef.current) {
|
||||
cancelAnimationFrame(animationFrameRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
const containerStyle = React.useMemo<React.CSSProperties>(() => ({
|
||||
borderRadius: '0px 0px 5px 5px',
|
||||
overflow: 'hidden',
|
||||
backgroundColor: 'white',
|
||||
contain: 'layout style paint',
|
||||
isolation: 'isolate' as React.CSSProperties['isolation']
|
||||
}), []);
|
||||
|
||||
const canvasStyle = React.useMemo(() => ({
|
||||
display: 'block',
|
||||
imageRendering: 'crisp-edges' as const,
|
||||
willChange: 'contents',
|
||||
backfaceVisibility: 'hidden' as const,
|
||||
transform: 'translateZ(0)',
|
||||
maxWidth: '100%',
|
||||
maxHeight: '100%'
|
||||
}), []);
|
||||
|
||||
return (
|
||||
<div style={containerStyle}>
|
||||
<canvas
|
||||
tabIndex={0}
|
||||
ref={canvasRef}
|
||||
height={height}
|
||||
width={width}
|
||||
style={canvasStyle}
|
||||
/>
|
||||
{datePickerInfo && (
|
||||
<DatePicker
|
||||
coordinates={datePickerInfo.coordinates}
|
||||
selector={datePickerInfo.selector}
|
||||
onClose={() => setDatePickerInfo(null)}
|
||||
/>
|
||||
)}
|
||||
{dropdownInfo && (
|
||||
<Dropdown
|
||||
coordinates={dropdownInfo.coordinates}
|
||||
selector={dropdownInfo.selector}
|
||||
options={dropdownInfo.options}
|
||||
onClose={() => setDropdownInfo(null)}
|
||||
/>
|
||||
)}
|
||||
{timePickerInfo && (
|
||||
<TimePicker
|
||||
coordinates={timePickerInfo.coordinates}
|
||||
selector={timePickerInfo.selector}
|
||||
onClose={() => setTimePickerInfo(null)}
|
||||
/>
|
||||
)}
|
||||
{dateTimeLocalInfo && (
|
||||
<DateTimeLocalPicker
|
||||
coordinates={dateTimeLocalInfo.coordinates}
|
||||
selector={dateTimeLocalInfo.selector}
|
||||
onClose={() => setDateTimeLocalInfo(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
|
||||
export default memo(Canvas);
|
||||
87
legacy/src/Highlighter.tsx
Normal file
87
legacy/src/Highlighter.tsx
Normal file
@@ -0,0 +1,87 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import styled from "styled-components";
|
||||
import { coordinateMapper } from '../../helpers/coordinateMapper';
|
||||
|
||||
interface HighlighterProps {
|
||||
unmodifiedRect: DOMRect;
|
||||
displayedSelector: string;
|
||||
width: number;
|
||||
height: number;
|
||||
canvasRect: DOMRect;
|
||||
};
|
||||
|
||||
const HighlighterComponent = ({ unmodifiedRect, displayedSelector = '', width, height, canvasRect }: HighlighterProps) => {
|
||||
if (!unmodifiedRect) {
|
||||
return null;
|
||||
} else {
|
||||
const rect = useMemo(() => {
|
||||
const mappedRect = coordinateMapper.mapBrowserRectToCanvas(unmodifiedRect);
|
||||
return {
|
||||
top: mappedRect.top + canvasRect.top + window.scrollY,
|
||||
left: mappedRect.left + canvasRect.left + window.scrollX,
|
||||
width: mappedRect.width,
|
||||
height: mappedRect.height,
|
||||
};
|
||||
}, [unmodifiedRect, canvasRect.top, canvasRect.left]);
|
||||
|
||||
|
||||
return (
|
||||
<div>
|
||||
<HighlighterOutline
|
||||
id="Highlighter-outline"
|
||||
top={rect.top}
|
||||
left={rect.left}
|
||||
width={rect.width}
|
||||
height={rect.height}
|
||||
/>
|
||||
{/* <HighlighterLabel
|
||||
id="Highlighter-label"
|
||||
top={rect.top + rect.height + 8}
|
||||
left={rect.left}
|
||||
>
|
||||
{displayedSelector}
|
||||
</HighlighterLabel> */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const Highlighter = React.memo(HighlighterComponent);
|
||||
|
||||
const HighlighterOutline = styled.div<HighlighterOutlineProps>`
|
||||
box-sizing: border-box;
|
||||
pointer-events: none !important;
|
||||
position: fixed !important;
|
||||
background: #ff5d5b26 !important;
|
||||
outline: 2px solid #ff00c3 !important;
|
||||
z-index: 2147483647 !important;
|
||||
top: ${(p: HighlighterOutlineProps) => p.top}px;
|
||||
left: ${(p: HighlighterOutlineProps) => p.left}px;
|
||||
width: ${(p: HighlighterOutlineProps) => p.width}px;
|
||||
height: ${(p: HighlighterOutlineProps) => p.height}px;
|
||||
`;
|
||||
|
||||
const HighlighterLabel = styled.div<HighlighterLabelProps>`
|
||||
pointer-events: none !important;
|
||||
position: fixed !important;
|
||||
background: #080a0b !important;
|
||||
color: white !important;
|
||||
padding: 8px !important;
|
||||
font-family: monospace !important;
|
||||
border-radius: 5px !important;
|
||||
z-index: 2147483647 !important;
|
||||
top: ${(p: HighlighterLabelProps) => p.top}px;
|
||||
left: ${(p: HighlighterLabelProps) => p.left}px;
|
||||
`;
|
||||
|
||||
interface HighlighterLabelProps {
|
||||
top: number;
|
||||
left: number;
|
||||
}
|
||||
|
||||
interface HighlighterOutlineProps {
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
94
legacy/src/coordinateMapper.ts
Normal file
94
legacy/src/coordinateMapper.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
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();
|
||||
139
legacy/src/inputHelpers.ts
Normal file
139
legacy/src/inputHelpers.ts
Normal file
@@ -0,0 +1,139 @@
|
||||
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);
|
||||
};
|
||||
Reference in New Issue
Block a user