From d84371e17ef4397a9dfd104af8e8c9ef494eb5c2 Mon Sep 17 00:00:00 2001 From: Delirium Date: Mon, 19 Feb 2024 16:48:37 +0100 Subject: [PATCH] fix(tracker): change canvas scaling (#1894); fix canvas replay * fix(tracker): change canvas scaling * fix(tracker): 12.0.3 * fix(tracker): 12.0.3 --- .../app/player/web/managers/CanvasManager.ts | 11 +++---- tracker/tracker/CHANGELOG.md | 4 +++ tracker/tracker/package.json | 2 +- tracker/tracker/src/main/app/canvas.ts | 33 ++++++++++++++++--- tracker/tracker/src/main/app/index.ts | 3 ++ 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/frontend/app/player/web/managers/CanvasManager.ts b/frontend/app/player/web/managers/CanvasManager.ts index a4e38a550..03d417985 100644 --- a/frontend/app/player/web/managers/CanvasManager.ts +++ b/frontend/app/player/web/managers/CanvasManager.ts @@ -2,8 +2,6 @@ import { VElement } from "Player/web/managers/DOM/VirtualDOM"; export default class CanvasManager { private fileData: string | undefined; - private canvasEl: HTMLVideoElement - private canvasCtx: CanvasRenderingContext2D | null = null; private videoTag = document.createElement('video') private lastTs = 0; @@ -38,10 +36,6 @@ export default class CanvasManager { this.videoTag.setAttribute('crossorigin', 'anonymous'); this.videoTag.src = this.fileData; this.videoTag.currentTime = 0; - - const node = this.getNode(parseInt(this.nodeId, 10)) as unknown as VElement - this.canvasCtx = (node.node as HTMLCanvasElement).getContext('2d'); - this.canvasEl = node.node as HTMLVideoElement; } move(t: number) { @@ -49,11 +43,14 @@ export default class CanvasManager { this.lastTs = t; const playTime = t - this.delta if (playTime > 0) { + const node = this.getNode(parseInt(this.nodeId, 10)) as unknown as VElement + const canvasCtx = (node.node as HTMLCanvasElement).getContext('2d'); + const canvasEl = node.node as HTMLVideoElement; if (!this.videoTag.paused) { void this.videoTag.pause() } this.videoTag.currentTime = playTime/1000; - this.canvasCtx?.drawImage(this.videoTag, 0, 0, this.canvasEl.width, this.canvasEl.height); + canvasCtx?.drawImage(this.videoTag, 0, 0, canvasEl.width, canvasEl.height); } } } \ No newline at end of file diff --git a/tracker/tracker/CHANGELOG.md b/tracker/tracker/CHANGELOG.md index 8e2cd2fc4..84f9ca16e 100644 --- a/tracker/tracker/CHANGELOG.md +++ b/tracker/tracker/CHANGELOG.md @@ -1,3 +1,7 @@ +# 12.0.3 + +- fixed scaling option for canvas (to ignore window.devicePixelRatio and always render the canvas as 1) + # 12.0.2 - fix for canvas snapshot check diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 97a059bca..04c7d54ac 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "12.0.2", + "version": "12.0.3", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/main/app/canvas.ts b/tracker/tracker/src/main/app/canvas.ts index 74e505fab..f2c7934e9 100644 --- a/tracker/tracker/src/main/app/canvas.ts +++ b/tracker/tracker/src/main/app/canvas.ts @@ -6,12 +6,14 @@ interface CanvasSnapshot { images: { data: string; id: number }[] createdAt: number paused: boolean + dummy: HTMLCanvasElement } interface Options { fps: number quality: 'low' | 'medium' | 'high' isDebug?: boolean + fixedScaling?: boolean } class CanvasRecorder { @@ -84,6 +86,7 @@ class CanvasRecorder { images: [], createdAt: ts, paused: false, + dummy: document.createElement('canvas'), } const canvasMsg = CanvasNode(id.toString(), ts) this.app.send(canvasMsg as Message) @@ -95,7 +98,12 @@ class CanvasRecorder { clearInterval(int) } else { if (!this.snapshots[id].paused) { - const snapshot = captureSnapshot(canvas, this.options.quality) + const snapshot = captureSnapshot( + canvas, + this.options.quality, + this.snapshots[id].dummy, + this.options.fixedScaling, + ) this.snapshots[id].images.push({ id: this.app.timestamp(), data: snapshot }) if (this.snapshots[id].images.length > 9) { this.sendSnaps(this.snapshots[id].images, id, this.snapshots[id].createdAt) @@ -143,14 +151,31 @@ class CanvasRecorder { } const qualityInt = { - low: 0.33, + low: 0.35, medium: 0.55, high: 0.8, } -function captureSnapshot(canvas: HTMLCanvasElement, quality: 'low' | 'medium' | 'high' = 'medium') { +function captureSnapshot( + canvas: HTMLCanvasElement, + quality: 'low' | 'medium' | 'high' = 'medium', + dummy: HTMLCanvasElement, + fixedScaling = false, +) { const imageFormat = 'image/jpeg' // or /png' - return canvas.toDataURL(imageFormat, qualityInt[quality]) + if (fixedScaling) { + const canvasScaleRatio = window.devicePixelRatio || 1 + dummy.width = canvas.width / canvasScaleRatio + dummy.height = canvas.height / canvasScaleRatio + const ctx = dummy.getContext('2d') + if (!ctx) { + return '' + } + ctx.drawImage(canvas, 0, 0, dummy.width, dummy.height) + return dummy.toDataURL(imageFormat, qualityInt[quality]) + } else { + return canvas.toDataURL(imageFormat, qualityInt[quality]) + } } function dataUrlToBlob(dataUrl: string): [Blob, Uint8Array] | null { diff --git a/tracker/tracker/src/main/app/index.ts b/tracker/tracker/src/main/app/index.ts index ef34dc67a..a2872a877 100644 --- a/tracker/tracker/src/main/app/index.ts +++ b/tracker/tracker/src/main/app/index.ts @@ -117,6 +117,7 @@ type AppOptions = { __debug_report_edp: string | null __debug__?: ILogLevel __save_canvas_locally?: boolean + fixedCanvasScaling?: boolean localStorage: Storage | null sessionStorage: Storage | null forceSingleTab?: boolean @@ -211,6 +212,7 @@ export default class App { disableStringDict: false, forceSingleTab: false, assistSocketHost: '', + fixedCanvasScaling: false, }, options, ) @@ -1063,6 +1065,7 @@ export default class App { fps: canvasFPS, quality: canvasQuality, isDebug: this.options.__save_canvas_locally, + fixedScaling: this.options.fixedCanvasScaling, }) this.canvasRecorder.startTracking() }