'html2canvas is not respecting windowWidth option

The goal:

I'm writing a script that saves the contents of an element on the page to a PDF when the user clicks a link. This is needed several times throughout the site so I'm trying to make it as generic as possible. To that end, I'm storing all the settings in custom data attributes of the link element. The target element is responsive but I need it to always save to PDF as if the page were a fixed width.

The problem:

In order to ensure a fixed layout regardless of window width I am setting the windowWidth option to a fixed value. However, the resulting image is still being rendered according to the current window width instead of my specified width when the link is clicked.

My code:

Using minified html2canvas from: https://html2canvas.hertzen.com/

Using minified umd jspdf from: https://github.com/parallax/jsPDF/tree/master/dist

The HTML + CSS is just a simple flex element for testing with a media query breakpoint at 768px that swaps flex-direction.

jQuery(document).ready(function(){
    jQuery(".save2pdf-button").on("click", function(e){
        e.preventDefault();
        
        // Gather settings from the page
        var target_selector = jQuery(this).data("target") || jQuery(this).attr('href') || '#save-this';
        var target = jQuery(target_selector)[0];
        if (!(target instanceof HTMLElement)) { // Validate target existence
            return;
        }
        var window_width = parseFloat(jQuery(this).data("render-width")) || Window.innerWidth;
        var format = jQuery(this).data("format") || 'fit';
        var orientation = jQuery(this).data("orientation") || 'p';
        var filename = jQuery(this).data("filename") || "download.pdf";
        
        // Set image render settings
        var html2canvas_options = {
            scale: 2,
            windowWidth: window_width
        };
        
        // Render element to JPEG
        html2canvas(target, html2canvas_options).then(function (canvas) {
            var imgData = canvas.toDataURL("image/jpeg", 1.0);
            
            if (format == "fit") {
                // Set the output size based on the element size
                format = [canvas.width, canvas.height];
                
                // Set the orientation according to aspect ratio
                if (canvas.height > canvas.width) {
                    orientation = 'p';
                }
                else {
                    orientation = 'l';
                }
            }
            
            // Create a new PDF object based on our settings
            var pdf = new jsPDF(orientation, 'px', format);
            
            // Scale the image to fit on the PDF
            var output_aspect_ratio = canvas.height/canvas.width;
            
            var output_width = pdf.internal.pageSize.getWidth();
            var output_height = output_width * output_aspect_ratio;
            
            // Add the image to the PDF and save it
            pdf.addImage(imgData, 'JPG', 0, 0, output_width, output_height);
            pdf.save(filename);
        });
        
    });
});

My research so far:

I read through the docs at https://html2canvas.hertzen.com/documentation but found them lacking.

Looking for similar issues I found this: HTML2Canvas Options Syntax but it has no solution. Thinking it might be that I'm using the wrong datatype for windowWidth, I went through and tried hardcoding it as an Int, Float, String (with and without 'px')... nothing worked.

Interestingly, when I randomly tried assigning my 'target' element to windowWidth it did produce a fixed result, which is what I want. I then tried to change the fixed output width by changing the width of my target element, assuming it was reading the elements width, but that didn't work. So it seems to work when provided an HTMLElement object, but I don't know how it's getting the fixed width from it. Also, the documentation seems to indicate that it's supposed to take a number, not an HTMLElement. Ideally I'd like to avoid changing the existing DOM elements or creating ones just to pass a value.

I tried downloading and using different versions of html2canvas from various other locations, no luck.

I tried putting my code in the onrendered: function(canvas){} callback instead of inside a promise.

Clearly I'm doing something wrong, I've looked over dozens of examples but nothing has shed light on my issue. Hopefully someone here can point out my mistake. Let me know if there's any additional info that would be helpful.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source