bubkoo / html-to-image

✂️ Generates an image from a DOM node using HTML5 canvas and SVG.
MIT License
5.4k stars 505 forks source link

Elements with internal scroll #388

Open dav-q opened 1 year ago

dav-q commented 1 year ago

Expected Behavior

the capture must be taken taking into account the positioning of the scroll where the user is in the child containers at the time of the capture

Current Behavior

the capture always takes the top of scrollable containers

Additional Context

I'm working with react, every time the user clicks a "screenshot" button, the root element is taken and passed as a parameter. The root element has a child container with maximum height and internal scroll (something like a chat message container). If the user takes the screenshot right when they are positioned at the bottom of the message container, the screenshot shows the messages at the top. https://codesandbox.io/s/snowy-feather-ex77v0

Your Environment

is this possible? Or is it simply not the essence of this library?

vivcat[bot] commented 1 year ago

👋 @dav-q

Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. To help make it easier for us to investigate your issue, please follow the contributing guidelines.

We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.

helloint commented 8 months ago

hope it can be resolved

gdeggau commented 8 months ago

@dav-q have you find any workaround? I'm facing the same issue.

dav-q commented 7 months ago

@gdeggau unfortunately not yet :disappointed:

gdeggau commented 7 months ago

@gdeggau unfortunately not yet 😞

I found a workaround for the issue. In my case the user can't scroll the page, I'm hiding the scrollbar with overflow: hidden and I was setting manually the scroll position with scrollTo({ top: somenumber }).

So I changed my code to have a div around the element with the scroll position. This div now has the overflow: hidden, position: relative and some height. And in the children component I have the styles with position: absolute and top: -somenegativevalue.

As I'm using React with emotion, that is the actually code that I'm using:

export const stylesHiddenScrollFields = {
  root: (newFieldHeight?: number) =>
    css({
      position: 'relative',
      overflow: 'hidden',
      ...(newFieldHeight && {
        height: newFieldHeight,
      }),
    }),
  field: (scrollTop: number) =>
    css({
      maxWidth: '100%',
      position: 'absolute',
      top: -scrollTop,
    }),
}
amerimnos commented 4 months ago

Increase the height value of the parent of the scroll element to the total height of the scroll element, capture it, and then restore it. Please refer to the logic below.

function captureTotalMassages() {
    document.querySelector('#chatTotalCopyBtn').addEventListener('click', function () {
        const firstMassageHeight = document.querySelector('.detail01').offsetHeight;
        const otherMassageHeight = $chatbotMessagesArea.scrollHeight;
        $chatbotMessagesAreaWrap.style.height = firstMassageHeight + otherMassageHeight + 'px';

        htmlToImage.toJpeg($chatbotMessagesArea, { quality: 0.95 })
            .then(function (dataUrl) {
                $chatbotMessagesAreaWrap.style.height = '';
                var link = document.createElement('a');
                link.download = 'massages.jpeg';
                link.href = dataUrl;
                link.click();
            });
    })
}