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

Question about cross-domain image rendering #3

Closed
khang-nd opened this issue Feb 7, 2023 · 2 comments
Closed

Question about cross-domain image rendering #3

khang-nd opened this issue Feb 7, 2023 · 2 comments
Labels

Comments

@khang-nd
Copy link

khang-nd commented Feb 7, 2023

Hello, thank you for making this, it works pretty well for my project compared to html2canvas & html-to-image.

Just a question out of curiosity, from my experience with html2canvas, as it primarily uses canvas for rendering, images from another domain need to go through a proxy to be drawn and exported from the canvas, but that doesn't seem to be the case with this lib, I'm able to render x-domain images normally without any proxy. What is the magic behind this one (how does it work)?

@qq15725
Copy link
Owner

qq15725 commented Feb 7, 2023

The main difference should be in embedding HTMLImageElement

  1. html2canvs by using img.crossOrigin

    https://github.com/niklasvh/html2canvas/blob/v1.4.1/src/core/cache-storage.ts#L96-L99

    //ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
    if (isInlineBase64Image(src) || useCORS) {
      img.crossOrigin = 'anonymous';
    }
  2. html-to-image and modern-screenshot by using window.fetch convert img.src to the base64 dataURL

    https://github.com/bubkoo/html-to-image/blob/v1.11.11/src/embed-images.ts#L53-L55

    const url = isImageElement ? clonedNode.src : clonedNode.href.baseVal
    
    const dataURL = await resourceToDataURL(url, getMimeType(url), options)

    https://github.com/qq15725/modern-screenshot/blob/v4.2.12/src/embed-image-element.ts#L9-L26

    if (isImageElement(clone) && !isDataUrl(clone.currentSrc || clone.src)) {
      const currentSrc = clone.currentSrc || clone.src
      clone.srcset = ''
      clone.dataset.originalSrc = currentSrc
      return [
        fetchDataUrl(currentSrc, context, true).then(url => {
          clone.src = url
        }),
      ]
    } else if (isSVGElementNode(clone) && !isDataUrl(clone.href.baseVal)) {
      const currentSrc = clone.href.baseVal
      clone.dataset.originalSrc = currentSrc
      return [
        fetchDataUrl(currentSrc, context, true).then(url => {
          clone.href.baseVal = url
        }),
      ]
    }

The embedded dataURI img does not trigger a CORS error when the foreign-object svg is finally rendered to the canvas


References:

https://stackoverflow.com/a/22716873

https://stackoverflow.com/a/20285053

@khang-nd
Copy link
Author

khang-nd commented Feb 7, 2023

Wonderful, thank you for the detailed insights 😃

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

No branches or pull requests

2 participants