Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] html2canvas Fails with preserveDrawingBuffer: true in deck.gl #8896

Closed
1 of 7 tasks
athomann opened this issue May 14, 2024 · 4 comments · Fixed by #8945
Closed
1 of 7 tasks

[Bug] html2canvas Fails with preserveDrawingBuffer: true in deck.gl #8896

athomann opened this issue May 14, 2024 · 4 comments · Fixed by #8945
Assignees
Labels

Comments

@athomann
Copy link

Description

When attempting to use html2canvas to capture a screenshot of a deck.gl canvas with the preserveDrawingBuffer option set to true, the operation fails. I'm only able to see the base map from react-map-gl. The error message suggests that preserveDrawingBuffer is set to false, despite being explicitly set to true. However, directly using the toDataURL method on the canvas works as expected and does not produce any error.

I had this working in previous versions of deck.gl, but need further testing.

Flavors

  • Script tag
  • React
  • Python/Jupyter notebook
  • MapboxOverlay
  • GoogleMapsOverlay
  • CartoLayer
  • ArcGIS

Expected Behavior

html2canvas should be able to capture the canvas image when preserveDrawingBuffer is set to true, without errors suggesting otherwise.

Actual Behavior
html2canvas fails to capture the canvas, with an error message incorrectly stating that preserveDrawingBuffer is set to false. Direct usage of toDataURL on the canvas works correctly, indicating that preserveDrawingBuffer is indeed set to true.

Steps to Reproduce

  1. Set up a deck.gl environment with any basic layer and base map.
  2. Configure the deck.gl instance with glOptions including { preserveDrawingBuffer: true }.
  3. Attempt to capture the canvas using html2canvas.
  4. Observe the failure and error message indicating that preserveDrawingBuffer is set to false.
  5. Use the toDataURL method directly on the canvas to successfully capture the image.

Environment

deck.gl version: 9.0.14
Browser and version: All
OS: Mac OS Sonoma

Logs

No response

@athomann athomann added the bug label May 14, 2024
@Pessimistress
Copy link
Collaborator

glOptions is replaced by deviceProps in v9. The documentation should be updated.

@Pessimistress Pessimistress added doc and removed bug labels May 14, 2024
@athomann
Copy link
Author

Okay, great. I briefly see device mentioned in the updates section but not about deviceProps. I still see glOptions in https://deck.gl/docs/api-reference/core/deck#gloptions

@akre54
Copy link
Collaborator

akre54 commented Jun 20, 2024

You also might want to look into CropTarget.fromElement instead of html2canvas. It's faster and native.

Something like this:

const cropTarget = await CropTarget.fromElement(root);
const controller = new CaptureController();

const stream = await navigator.mediaDevices.getDisplayMedia({
  controller,
  preferCurrentTab: true,
  cursor: "never",

  frameRate: fps,
  audio: false,
  video: {
    width,
    height,
    frameRate,
    displaySurface: "browser",
    resizeMode: "none",
    logicalSurface: true,
  },
});
const [track] = stream.getVideoTracks();

controller.setFocusBehavior("focus-captured-surface");
await root.requestFullscreen({ navigationUI: "hide" });

await track.cropTo(cropTarget);

const processor = new MediaStreamTrackProcessor({ track });
const reader = processor.readable.getReader();
const result = await reader.read();
const screenFrame = result.value;

@akre54
Copy link
Collaborator

akre54 commented Jun 20, 2024

If you don't need to composite html with the canvas, then the process is even simpler. Just use this:

const track = canvas.captureStream(0).getVideoTracks()[0]
const mediaProcessor = new MediaStreamTrackProcessor(track)
const reader = mediaProcessor.readable.getReader()

track.requestFrame()
const result = await reader.read()
const frame = result.value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants